Quick Tip: named_scope

Posted by Curtis Miller on August 31, 2008

Have you ever found yourself writing queries like this?

User.find(:all, :conditions => ['state = ? AND created_at > ? AND created_at <= ?', 'active', start_date, end_date], :limit => 5)

I suppose you could refactor this into a custom finder that did the heavy lifting for you…

User.find_all_active_in_date_range(start_date, end_date)

But what if you need that same query where the state is ‘pending'? Create another custom finder? Modify it so it takes another parameter for state? Wouldn't it be nice if you could create some kind of reusable snippet that could be chained together to create a custom finder? Well, look no further. As of Rails 2.1, such a thing exists and it's called named_scope.

Let's refactor that code using named_scope.

app/models/user.rb

class User < ActiveRecord::Base
  named_scope :active, :conditions => { :state => 'active' }
  named_scope :between, lambda { |starts, ends| { :conditions => ['created_at > ? AND created_at <= ?', starts, ends] } }
end

The lambda is simply so we can accept parameters into the named scope call. Named scopes are easily chainable, so to get the desired query we can call:

User.active.between(start_date, end_date)

Plus, if we want to add another condition, we just created another reusable named_scope and add it to the end.

app/models/user.rb

class User < ActiveRecord::Base
  named_scope :active, :conditions => { :state => 'active' }
  named_scope :between, lambda { |starts, ends| { :conditions => ['created_at > ? AND created_at <= ?', starts, ends] } }
  named_scope :limit, lambda { |num| { :limit => num } }
end

And we have our original query. This is much more readable and maintainable than the previous code we were looking at. The named scopes can also be reused when another query comes up with those conditions.

User.active.between(start_date, end_date).limit(5)

There's so much more you can do with named_scope, so check it out.

References

Need web application development, maintenance for your existing app, or a third party code review?

Velocity Labs can help.

Hire us!