Simplify ActiveRecord Aggregates and Other Goodies via named_scope

We’ve been huge fans of named_scope since its introduction in Rails 2.1. If you are new to the named_scope concept, please read Ryan Daigle’s intro to named_scope and watch Ryan Bates’ named_scope RailsCast. Ryan Daigle also had a good follow up article explaining his utility scope gem.

With a recent project, we really started utilizing extensions with named_scope which is very powerful and cleaned up our code considerably.

For example, let’s say you have an issue tracking system that has an Entry model that belongs_to both a User model and a Project model. Using named_scope, we can easily access Entries for a date range filtered to both the Project and User level using named_scope lambdas:

To find the Entries for the last week for the first user, we would simply do:

u = User.first
u.entries.by_date(1.week.ago, Time.now)

To find the Entries for the last week for the first project, we would simply do:

p = Project.first
p.entries.by_date(1.week.ago, Time.now)

What happens if we want to see the sum of hours worked for a date range? This is where extensions come in very handy. Let’s add a “total_duration” extension to our named_scope:

Now to get the duration for the past week for the first user we simply do:

u = User.first
u.entries.by_date(1.week.ago, Time.now).total_duration

with similar logic at the project level.

To group all of the entries by project, we would do:

If you need the lambda arguments inside your named_scope extension, you will need to use “self.proxy_options”. For example, let’s say you need the from and to dates in order to calculate the average duration per weekday. That code would look something like this:

In the above example, “weekday_count” is a custom method we created to calculate the number of weekdays between 2 given dates.

The opportunities to simplify code using named_scope is great. As I was writing this post, one of our team members, Jason Derrett, created a named_scope to wrap a Xapian full text search into a Lesson model:

In this example, using Xapian to search for a keyword becomes as simple as:

Lesson.find_with_xapian "fishing"

How cool is that?!?

Are there any other cool named_scope tricks out there that any of you are using?

  •