Making Better Use of named_scope
In Ruby on Rails 2.1, a great little feature called named_scope was added that really makes complicated finds a whole lot easier. I’m going to walk through one way you can use scopes to clean up your code, and if you want more information, Ryan Daigle’s post is a good starting point.
The Situation
For a project I’m working on, users can submit reviews, and I needed a way to access a user’s friends’ reviews. At first, I considered adding a method like the following to my User model:
class User < ActiveRecord::Base
def friends_reviews
Review.find(:all,
:joins => "JOIN friendships ON user_id = #{self.id}",
:conditions => "friendships.friend_id = reviews.user_id"
)
end
end
Named Scopes to the Rescue
While this method would work fine, there are several issues. For one, what if I want to change parameters on the find, like limiting it to 5 entries, or sorting by date? I would have to add parameters to the method, and it would start to get complicated. Instead, I created a scope in my Review model:
class Review < ActiveRecord::Base
named_scope :by_friends_of, lambda { |user|
{
:joins => "JOIN friendships ON user_id = #{user.id}",
:conditions => "friendships.friend_id = reviews.user_id"
}
}
end
Now, to get the reviews I want, I can call Review.by_friends_of(user) and it will get me reviews by user’s friends. What’s even better, since it’s a scope, I can modify it. For instance, Review.by_friends_of(user).all(:limit => 10, :order => "created_at DESC") will limit it to 10 reviews, sorted by creation date. I can even use other scopes I might have created, like: Review.by_friends_of(user).published.all(:limit => 20), and so on.
Scopes are super useful, and recently I’ve started to use them for just about everything. Definitely try them out, they’ll make your code a lot more efficient and useful.

1 Comment
Colin Devroe 09 Jan 2009 at 8:59AM
Looks nice and efficient.