Reputation: 5907
I have the following named scopes in my rails app:
scope :published, :conditions => {:status => 'published'}
scope :coming_soon, :conditions => {:status => 'coming_soon'}
scope :in_development, :conditions => {:status => 'in_development'}
scope :cancelled, :conditions => {:status => 'cancelld'}
I'm having trouble writing one that combines "published" and "combing soon." Here's what I've tried.
scope :public, :conditions => {"status == published || status == coming_soon"}
Any ideas?
Upvotes: 1
Views: 426
Reputation: 96544
Rails 2: named_scope :public, :status => ['published', 'coming_soon']
Rails 3: scope :public, where(:status => ['published', 'coming_soon'])
Rails will see the array and use the IN
operator in the sql.
An a note: The other approach (chain existing scopes) of Article.published.coming_soon would NOT work because an Article can't be both of those things at the time time or be a subset of each other.
Another note: Careful when you want something dependent on a variable parameter. For example say you wanted "future appointment" for a scheduling system, you might write
[This is invalid]
Rails 2: named_scope :upcoming_appts, :conditions => (['appt_dt > ?', Time.now])
Rails 3: scope :upcoming_appts, where(['appt_dt > ?', Time.now])
However there's a problem: The Time.now
will get evaluated the first time the class is evaluated not when the scope itself is evaluated.
To overcome this you use a lambda (silly name but basically means anonymous function - or to put it even simpler 'a function that doesn't actually have a name') as follows:
[This is valid]
Rails 2: named_scope :upcoming_appts, lambda {:conditions => (['appt_dt > ?', Time.now])}
Rails 3: scope :upcoming_appts, lambda {where(['appt_dt >= ?', Time.now])}
This scope will now get evaluated at execution time each time - it is used - so Time.now will be the actual current date-time.
Upvotes: 3