Rails - or to be more precise - ActiveRecord scopes can be a huge time saver. That is, unless you have a number of multiple conditions that stack onto each other. But if you are in need of an "advanced search" feature you will likely end up with something like the following:

condition1 = first_name && { :conditions => [ "first_name LIKE ?", "#{first_name}%" ] }
condition2 = last_name && { :conditions => [ "last_name LIKE ?", "#{last_name}%" ] }
condition3 = min_age &amp;&amp; { :conditions => [ "birthday < ?", Date.now - min_age.years ] }

with_scope :find => condition1 do
  with_scope :find => condition2 do
    with_scope :find => condition3 do
      User.find :all, ...

<p>That certainly is ok enough, but what I don't like here is the wrapping of all those with_scopes into each other. What I want instead would look more like this</p>

scope = User.scope scope.conditions "firstname LIKE ?", "#{firstname}%" if firstname scope.conditions "lastname LIKE ?", "#{lastname}%" if lastname scope.conditions "birthday < ?", Date.now - minage.years if minage scope.find :all, ...

Not only is this five lines of code compared to eleven. I even think this expresses more clearly what is going on here: namely that we stack a number of conditions onto each other. Sadly the ActiveRecord interface doesn't allow for something like that. But with Ruby so flexible it is easily possible to chew up the original interface and come up with something that matches my intent. And while we are at it: this way we can work around some bug limitation that occurs when stacking with_scopes: ActiveRecord doesn't like multiple :join parameters to scopes. Or at least it didn't like them...

So this is the code. I hope I managed to to without any typos... Have a great week!

Recommended reading

You want me to add a link here? Just write a comment...