Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Active Record Queries  ›  Lesson

Ordering, Limits and Scopes

Scopes 12 minorder, limit and offset shape a result list, and scopes give reusable query pieces names so controllers read like sentences and can chain them.

Ordering, Limits and Scopes

"The five newest available books" appears on the home page, in an email and in the API. Writing Book.where(available: true).order(created_at: :desc).limit(5) in three places is three chances to get it slightly different. Scopes give the pieces names, and ordering methods finish the query.

The rule

Name the filter as a scope, then chain: filter, order, limit.

Ordering and limiting:

Book.order(:title)                         # A to Z
Book.order(pages: :desc)                   # longest first
Book.order(author: :asc, title: :asc)      # by author, then title
Book.order(created_at: :desc).limit(5)     # five newest
Book.order(:id).limit(20).offset(40)       # the third page of 20
Book.order(:title).reverse_order           # flip an existing order

Scopes are named, reusable relations defined on the model:

class Book < ApplicationRecord
  scope :available, -> { where(available: true) }
  scope :long,      -> { where("pages > ?", 500) }
  scope :newest,    -> { order(created_at: :desc) }
  scope :by_author, ->(name) { where(author: name) }
end

Book.available.newest.limit(5)
Book.available.long.by_author("Tolkien")

A scope is a lambda (->) that returns a relation. It can take arguments. Scopes also work through associations: member.reviewed_books.available.

A scope and a class method (def self.available; where(available: true); end) are almost the same. The difference: if a scope's body returns nil or false, the scope returns all instead, so a chain never breaks.

default_scope applies a condition to every query on the model. It sounds convenient but surprises people later, because it also affects creates and associations. Prefer named scopes.

The shortcut

Read the request as a sentence: "[which] [in what order] [how many]". Each "which" phrase becomes a scope; the order becomes order; the count becomes limit. Chain them in that order.

"The three longest available books by Pratchett"Step 1 of 4
  1. Which

    "available", "by Pratchett": scopes available and by_author("Pratchett").

The trap is limit without order. The database is free to return rows in any order, so "the first five" changes between runs.

Drills

Answer fast — trust the rule.

quick drill

Which call lists books with the most pages first?

quick drill

How do you define a scope for books under 200 pages?

quick drill

Pages hold 20 books each. Which call gets page 3?

quick drill

A scope's lambda returns nil for a blank argument. What does calling the scope return?

Remember

  • Name the filter as a scope, then chain: filter, order, limit.
  • Shortcut: which, in what order, how many.
  • Trap: limit without order, and default_scope surprises.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainTurn repeated queries into scopes

The home page shows the five newest available books, and a sidebar shows available books by one author. Write two scopes on Book and the two chained calls, and explain one difference between a scope and a class method that returns nil.