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")


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

# 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 ||] } }

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.






3 responses to “How great is named_scope?”

  1. Brian Avatar

    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?

  2. Dave Avatar

    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.

  3. Brian Avatar

    That’s a good rule of thumb: if you’re tempted to add :conditions in your code, use a named_scope instead.

Leave a Reply

Your email address will not be published. Required fields are marked *