How great is named_scope?
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.

11/01/2009 at 12:46 am Permalink
Dave, I found this entry catching up on my reading after the holidays.
I’m also a huge fan of named_scope, and has_finder before it. But one problem I have had with it is the tendency to make up new named scopes ad hoc. I worry that they’re inconsistent and obscure.
Do you have any wisdom on a strategy for when and where to create named scopes?
11/01/2009 at 11:19 am Permalink
Hi there, Brian! I can’t say that I have a definitive strategy, but I do find myself making named scopes for model attributes or sets of attributes that collect records. As much as possible, I want to avoid having anything use a :conditions on my model. I prefer to keep the details of the model inside the model.
11/01/2009 at 3:14 pm Permalink
That’s a good rule of thumb: if you’re tempted to add :conditions in your code, use a named_scope instead.