ActiveRecord::NamedScopes (2.3.x) obtaining the SQL conditions

Posted Almost 12 years ago. Visible to the public.

It's a good pratice to chain several named scopes like:

Property.listable.for_2_or_more_guests.best_10_properties

Now, to make the lesson more valuable let's assume the following code:

Property.scoped(:conditions => "foo = 2").scoped(:conditions => "foo2 IS NOT NULL")

Next, if you want to be able to fetch the underlying conditions scope generated by ActiveRecord. You must do this:

Property.scoped(:conditions => "foo = 2").scoped(:conditions => "foo2 IS NOT NULL").scope(:find)
# => {:conditions => "(foo = 2) AND (foo2 IS NOT NULL)"}

This is particular interesting if you want to combine complex named scopes with raw SQL (i.e. complex selects with functions) and inject the conditions on the where clause.
Unfortunately if your scope is composed only by hashes you will get an hash aswell:

class Property < ActiveRecord::Base
  named_scope :listable, :conditions => { :listable => true }
end
  
Property.listable.scope(:find)
# => {:conditions => { :listable => true }}

The only way to get around this is by forcing a string conditions scope

Property.listable.scoped(:conditions => "1=1").scope(:find)
# => {:conditions => "(1=1) AND (`properties`.`listable` = 1)"}

Also another method of obtaining the conditions is through proxy_options but be aware there is a gotcha!

Property.scoped(:conditions => "foo = 2").proxy_options
# => {:conditions => "foo=2" }

Property.scoped(:conditions => "foo = 2").scoped(:conditions => "foo2 IS NOT NULL").proxy_options
# => {:conditions => "foo2 IS NOT NULL"}

As you can see, proxy_options only returns conditions for last scope, but one possible use case of this is using proxy_options to combine scopes through OR's

Last edit
Almost 12 years ago
Posted to HouseTrip Deck (2012-07-04 09:45)