2009-07-23 7 views
5

J'ai une action index dans des rails qui peut gérer un certain nombre params par exemple:conditions dynamiques trouver dans le dossier actif

params[:first_name] # can be nil or first_name 
params[:age]  # can be nil or age 
params[:country] # can be nil or country 

Lors de la recherche des utilisateurs que je voudrais et toutes les conditions qui ne sont pas nulles. Cela me donne 8 permutations des conditions de recherche.

Comment puis-je garder mon code DRY et flexible et ne pas finir avec un tas de if instructions juste pour créer les conditions de la recherche. Gardez à l'esprit que si aucune condition sont spécifiées, je veux juste revenir User.all

Répondre

1

Cela semble fonctionner assez bien:

conditions = params.slice(:first_name, :age, :country) 
hash = conditions.empty? ? {} : {:conditions => conditions} 
@users = User.all hash 
3

Que diriez-vous quelque chose comme:

conditions = params.only(:first_name, :age, :country) 
conditions = conditions.delete_if {|key, value| value.blank?} 

if conditions.empty? 
    User.all 
else 
    User.all(:conditions => conditions) 
end 
+0

Assez curieusement, mon params hash ne semble pas avoir une seule méthode –

0

Vous pouvez essayer Ambition, ou un certain nombre d'autres extensions ActiveRecord.

3

Je normalement utiliser named scopes pour quelque chose comme ceci:

class User < ActiveRecord::Base 
    named_scope :name_like, lambda {|name| {:conditions => ["first_name LIKE ?", "#{name}%"]}} 
    named_scope :age, lambda {|age| {:conditions => {:age => age}}} 
    named_scope :in_country, lambda {|country| {:conditions => {:country => country}}} 
end 

class UsersController < ActionController 
    def index 
    root = User 
    root = root.name_like(params[:first_name]) unless params[:first_name].blank? 
    root = root.age(params[:age]) unless params[:age].blank? 
    root = root.country(params[:country]) unless params[:age].blank? 

    @users = root.paginate(params[:page], :order => "first_name") 
    end 
end 

C'est ce que je fais normalement.

0

Cela fonctionne pour moi aussi

conditions = params[:search] ? params[:search].keep_if{|key, value| !value.blank?} : {} 
User.all(:conditions => conditions) 
1

James Healy réponse aide, je modifie le code à utiliser dans Rails 3.2 (au cas où quelqu'un besoin là-bas cela).

conditions = params.slice(:first_name, :age, :country) 
conditions = conditions.delete_if {|key, value| value.blank?} 

@users = User.where(conditions) 
0

Si vous arrive d'être sur un projet ancien (Rails 2.x) et très salissant, vous pourriez faire quelque chose comme ce qui suit pour ajouter de nouveaux champs à la requête originale.

Code d'origine:

User.find(:all, 
    :conditions => ['first_name LIKE ? AND age=? AND country=?', 
     "#{name}%", age, country] 

Ajout d'une nouvelle condition dynamique sur le terrain zip_code:

zip_code = params[:zip_code] # Can be blank 
zip_query = "AND zip_code = ?" unless zip_code.blank? 

User.find(:all, 
    :conditions => ['first_name LIKE ? AND age=? AND country=? #{zip_query}', 
     "#{name}%", age, country, zip_code].reject(&:blank?) 

Ajout d'un reject(&:blank?) aux tableaux conditions filtrera la valeur nil.

Remarque: Les autres réponses sont nettement meilleures si vous effectuez un codage à partir de zéro ou si vous effectuez un refactoring.

Questions connexes