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.

Posted on January 6, 2009
Tagged with: , , , , , ,

1 Comment

Avatar

Colin Devroe 09 Jan 2009 at 8:59AM

Looks nice and efficient.

Leave A Comment

Ajax-loader