Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic find conditions in active record

I have an index action in rails that can handle quite a few params eg:

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

When finding users I would like to AND all the conditions that are not nil. This gives me 8 permutations of the find conditions.

How can I can I keep my code DRY and flexible and not end up with a bunch of if statements just to build the conditions for the find. Keep in mind that if no conditions are specified I just want to return User.all

like image 451
Sam Saffron Avatar asked Jul 23 '09 03:07

Sam Saffron


Video Answer


4 Answers

How about something like:

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
like image 145
James Healy Avatar answered Oct 14 '22 05:10

James Healy


I would normally use named scopes for something like this:

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

That's what I normally do.

like image 32
François Beausoleil Avatar answered Oct 14 '22 05:10

François Beausoleil


This seems to work quite nicely:

conditions = params.slice(:first_name, :age, :country)
hash = conditions.empty? ? {} : {:conditions => conditions}
@users = User.all hash 
like image 21
Sam Saffron Avatar answered Oct 14 '22 05:10

Sam Saffron


Using James Healy answer, I modify the code to be used in Rails 3.2 (in case anyone out there need this).

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

@users = User.where(conditions)
like image 27
William Notowidagdo Avatar answered Oct 14 '22 03:10

William Notowidagdo