# Quick Tip: named_scope

> Building chainable, reusable query scopes in Rails 2.1 with named_scope

- Author: Curtis Miller
- Published: 2008-08-31
- Categories: rails, how-to
- Canonical URL: https://millarian.com/posts/quick-tip-named_scope/

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

- [Has finder functionality](http://ryandaigle.com/articles/2008/3/24/what-s-new-in-edge-rails-has-finder-functionality)
- [Named scope: It's not just for conditions, ya know?](http://ryandaigle.com/articles/2008/8/20/named-scope-it-s-not-just-for-conditions-ya-know)
- [Railscasts: named\_scope](http://railscasts.com/episodes/108)
