tdahlke
tdahlke

Reputation: 287

How to make a Rails 3 Dynamic Scope Conditional?

I'd like to make a dynamic named scope in rails 3 conditional on the arguments passed in. For example:

class Message < AR::Base
  scope :by_users, lambda {|user_ids| where(:user_id => user_ids) }
end

Message.by_users(user_ids)

However, I'd like to be able to call this scope even with an empty array of user_ids, and in that case not apply the where. The reason I want to do this inside the scope is I'm going to be chaining several of these together.

How do I make this work?

Upvotes: 24

Views: 18204

Answers (1)

Mike Lewis
Mike Lewis

Reputation: 64137

To answer your question you can do:

scope :by_users, lambda {|user_ids| 
  where(:user_id => user_ids) unless user_ids.empty?
}

However

I normally just use scope for simple operations(for readability and maintainability), anything after that and I just use class methods, so something like:

class Message < ActiveRecord::Base

  def self.by_users(users_id)
    if user_ids.empty?
      scoped
    else
      where(:user_id => users_id)
    end
  end

end

This will work in Rails 3 because where actually returns an ActiveRecord::Relation, in which you can chain more queries.

I'm also using #scoped, which will return an anonymous scope, which will allow you to chain queries.

In the end, it is up to you. I'm just giving you options.

Upvotes: 51

Related Questions