If you haven’t used named_scope in Rails 2.1+ yet, I suggest you learn about it ASAP. Prior versions of Rails had a plugin that could perform similar functions, but it’s nice to have it part of the core system.
What does it do?
It does just what it says. It gives you a way to utilize the power of with_scope but name it. The best way to show it is with an example.
Let’s say you have a user model. Users have a gender attribute and a activated flag. When operating on your user object, you could sprinkle your code with something like:
users = User.find(:all, :conditions => "gender = 'M'")
activated_males = User.find(:all,
:conditions => "gender = 'F' and activated = 1")
Or…
You could do this:
class User < ActiveRecord::Base
named_scope :activated, :conditions => "users.activated = 1"
named_scope :males, :conditions => "users.gender = 'M'"
named_scope :females, :conditions => "users.gender = 'F'"
# rest of your class
end
# Retrieved the activated users
users = User.activated
activated_males = User.activated.males
Note that you can string them together. You can also use all finder methods and the options will be merged together.
new_males = User.activated.males.find(:all,
:conditions => ["users.created_at > ?", 2.days.ago])
I can also get a little fancy and add an argument:
named_scope :recent, lambda
{ |*args| {:conditions => ["created_at >= ?", (args.first || 1.day.ago)] } }
Now, the previous example is:
new_males = User.activated.males.recent(2.days.ago)
In the end, your code is far more readable, safer, DRY, and easier to maintain. It’s a win all around.
Leave a Reply