Skip to content
Dave Strus edited this page Jul 16, 2015 · 1 revision

Have you noticed that records do not appear in a reliable order? We haven't been specifying an order when loading records, so it's not really predictable (though it may appear to be for a while). Let's set default scopes for our two models.

Let's use a default scope to always return posts in order of updated_at, with the most recently updated posts listed first.

app/models/post.rb

class Post < ActiveRecord::Base
  belongs_to :category
  default_scope { order(updated_at: :desc) }

Let's list categories in alphabetical order by name.

app/models/category.rb

class Category < ActiveRecord::Base
  has_many :posts
  default_scope { order(:name) }

Try it out in your browser and see if you can tell the difference. You can also watch your server output to see the new queries.

We are not yet showing the name of a post's category in the listing on posts/index. Let's add that, shall we? The code we want to change is actually in the slug partial. Let's also use this opportunity to split the div.tagline element into multiple lines.

_app/views/posts/slug.html.erb

<div class="tagline" title="<%= post.created_at %>">
  submitted <%= time_ago_in_words post.created_at %> ago
  to <%= link_to post.category.name, category_path(post.category) %>
</div>

Try that out, and watch your server output. We're making an awful lot of DB queries to grab individual categories. We can avoid those extra calls by chaining includes(:category) to the default scope for posts.

app/models/post.rb

class Post < ActiveRecord::Base
  belongs_to :category
  default_scope { order('updated_at DESC').includes(:category) }

Try it again, and notice the difference. While it's easy to see that there are fewer queries being run, you probably don't have enough records in your database to appreciate the performance difference. Changes like this can make a very big difference with a large database.

Let's commit our changes.

$ git add .
$ git commit -m "Set default scopes for Post and Category."