Utility Scopes
Summary
Utility scopes provides a collection of utilitarian named scopes for use with your ActiveRecord models.
Utility scopes was originally announced here and has expanded in scope and functionality since then thanks to user contributions. See the CHANGELOG for contribution details.
Utility scopes has the following dependencies:
- activerecord >= 2.1.0
- rspec >= 1.1.4 (for specs only, not runtime)
Installation
To install the utility_scopes gem run the following:
sudo gem install utility_scopesAnd to enable the scopes in your project just require utility_scopes
:
Rails
You can also specify the gem dependency if you’re running Rails 2.1 in your config/environment.rb
file:
- … config.gem “utility_scopes” end
You don’t need to require 'utility_scopes'
in this case as Rails will automatically require it.
Scopes
Most examples assume the following Article
class:
Named scopes are chainable by nature, meaning that the following is possible:
Article.with(:comments).except(1, 2, 3).ordered.limited(5)Any exceptions to chainable scopes will be specified in their section below.
With (eager-loading)
The with
scope let’s you eager load your model associations. So instead of having to invoke find(:all, :include => [:association1, :association2])
just pass these association names into
the with
named scope:
<ol>
<li>Get all articles and eager-load their comments, each comments’ user, article contributors</li>
<li>and the article author.
Article.with({ :comments => :user }, :contributors, :author)</li>
</ol>
<ol>
<li>Get all articles and eager-load their comments
Article.with(:comments)
Again, just pass in the same arguments into eager
that you would pass in as the :include
value to ActiveRecord::Base#find
Except
contributed by danielmorrison
except
excludes the given records from the result set:
Limited
limited
lets you place a limit on the number of results returned. By default
the scope will limit the result set to 10 results if no argument is passed in:
If you’re using will_paginate and don’t
pass an argument to the scope then the per_page
value that is used by will_paginate
will be used:
If you would like to specify a different default value you can do so on a per class basis
using default_limit
:
<ol>
<li>Set the default limit to be 15
class Article < ActiveRecord::Base
default_limit 15
end</li>
</ol>
Article.limited # Get the first 15 articles
Ordered
Note: the ordered
scope cannot be chained with any other order
clauses
ordered
lets you dynamically specify the ordering of your result set. If no
arguments are given it will default to created_at DESC
. (ordered
is also
available as order_by
and sort_by
)
- only available for jruby/ruby 1.9 Article.order_by_id # can be set as a sentence
If you would like to specify a different default sort order you can do so on a per class basis
using ordered_by
:
<ol>
<li>Set the default order to be “published_at <span class="caps">DESC</span>”
class Article < ActiveRecord::Base
ordered_by ‘published_at <span class="caps">DESC</span>’
end</li>
</ol>
Article.ordered # Get all articles ordered by “published_at <span class="caps">DESC</span>”
Article.ordered(“rank <span class="caps">ASC</span>”) # Get all articles ordered by “rank <span class="caps">ASC</span>”
The current default ordering for a class can always be accessed via default_ordering
:
PKs
only_pks
selects only the primary key column. This is useful when combined with the pks
class method to get the primary key values as an array: