2010-07-15 24 views
2

J'utilise la version bêta de Rails3, will_paginate gem, et le plugin geokit gem &. Comme le plugin geokit-rails ne semble pas supporter les portées Rails3 (y compris le symbole: origin), j'ai besoin d'utiliser la syntaxe .find.Combiner des tableaux de conditions dans Rails

Au lieu des champs d'application, je dois combiner deux séries de critères en format tableau:

J'ai une condition par défaut:

conditions = ["invoices.cancelled = ? AND invoices.paid = ?", false, false] 

je peut avoir besoin d'ajouter l'une des conditions suivantes au état par défaut, selon une sélection de l'interface utilisateur:

#aged 0 
lambda {["created_at IS NULL OR created_at < ?", Date.today + 30.days]} 
#aged 30 
lambda {["created_at >= ? AND created_at < ?", Date.today + 30.days, Date.today + 60.days]} 
#aged > 90 
lamdba {["created_at >= ?", Date.today + 90.days]} 

La requête résultante ressemble:

@invoices = Invoice.find(
    :all, 
    :conditions => conditions, 
    :origin => ll  #current_user's lat/lng pair 
).paginate(:per_page => @per_page, :page => params[:page]) 

Questions:

  1. Est-il un moyen facile de combiner ces deux tableaux de conditions (si j'ai rédigées de manière que correctement)
  2. Bien qu'il ne contribue pas au problème, est-il DRYer moyen de créer ces seaux de vieillissement?
  3. Existe-t-il un moyen d'utiliser les étendues Rails3 avec le plugin geokit-rails qui fonctionnera?

Merci pour votre temps.

Répondre

3

Essayez ceci:

ca = [["invoices.cancelled = ? AND invoices.paid = ?", false, false]] 

ca << ["created_at IS NULL OR created_at < ?", 
        Date.today + 30.days] if aged == 0 

ca << ["created_at >= ? AND created_at < ?", 
        Date.today + 30.days, Date.today + 60.days] if aged == 30 

ca << ["created_at >= ?", Date.today + 90.days] if aged > 30 

condition = [ca.map{|c| c[0] }.join(" AND "), *ca.map{|c| c[1..-1] }.flatten] 

Modifier approche 2

Singe patcher la classe Array. Créez un fichier appelé monkey_patch.rb dans le répertoire config/initializers.

class Array 
    def where(*args) 
    sql = args[0]  
    unless (sql.is_a?(String) and sql.present?) 
     return self 
    end  
    self[0] = self[0].present? ? " #{self[0]} AND #{sql} " : sql 
    self.concat(args[1..-1])  
    end 
end 

Maintenant, vous pouvez faire ceci:

cond = [] 
cond.where("id = ?", params[id]) if params[id].present? 
cond.where("state IN (?)", states) unless states.empty? 
User.all(:conditions => cond) 
+0

Merci, cela a bien fonctionné. – craig

+0

Je rencontre des problèmes pour que cela fonctionne dans l'utilisation de (?) Voir http://stackoverflow.com/questions/7097755/rails-2-3-5-problem-building-conditions-array-dynamically-when-using -in – Nick

+0

J'ai répondu à votre question. –