.order: ascending unless you say otherwise
Where the where/find_by course left off
ActiveRecord querying: where/find_by spent seven lessons on one question: which rows come back. .where and find_by narrow a table to the rows that match a condition, and that course ran every example on the scratch ScratchArticleQ table (title, category, published, views). This course asks a different question about the same rows: what order do they come back in, and how many do you want? That's .order and .limit, and they combine with everything the previous course taught.
Same rows, no guaranteed order
ScratchArticleQ.where(published: true)
This returns every published article, and nothing in the call says anything about order. PostgreSQL may return the rows in whatever order is convenient, often storage order for a small table without an index, but that's an implementation detail, not a promise. Two runs of the same query can come back in different orders, especially after an update or a vacuum. A view that renders articles in "whatever order the database felt like" has a bug that shows up the first time the database's internal bookkeeping changes.
.order(:column): one column, ascending
ScratchArticleQ.order(:views)
# SQL: SELECT "scratch_articles_q".* FROM "scratch_articles_q"
# ORDER BY "scratch_articles_q"."views" ASC
The scratch table has six rows with views of 5, 12, 15, 40, 90 and 100. A single symbol passed to .order generates ORDER BY column ASC: ascending, lowest value first. That's Rails' default direction, so you never have to type ASC:
ScratchArticleQ.order(:views).pluck(:title, :views)
# => [["Draft One", 5], ["Old Rails Notes", 12], ["JS Intro", 15],
# ["Hello Rails", 40], ["Postgres Indexes", 90], ["Rails Tips", 100]]
"Draft One" (5 views) comes first and "Rails Tips" (100 views) comes last. That's no surprise once you've seen it. The point is the wrong mental model it replaces: SQL without ORDER BY doesn't default to insertion order.
From this app: Catalog::Lesson.ordered
This project's Catalog::Lesson model has a scope that does this, and it runs every time a course page loads:
# app/models/catalog/lesson.rb
scope :ordered, -> { order(:position) }
Every lesson has an integer position column. Catalog::Lesson.ordered, and the for_course scope that chains where(course_id: ...).ordered, guarantee that lesson 3 of a course always renders after lesson 2, whatever order PostgreSQL hands the rows back in. Without that .order(:position), a course's lesson list would be one storage change away from showing "Variables" before "Setting Up Your Editor".
Symbols, strings and quoting
.order(:views) and .order("views") return the same rows here, but the SQL differs. With a symbol, ActiveRecord qualifies and quotes the column: ORDER BY "scratch_articles_q"."views" ASC, the same convention .where uses. A string goes into the SQL as written: ORDER BY views. The quoting is what lets a table have a column named order without PostgreSQL tripping on the reserved word, so the symbol (or hash) form is the safer default.
Key takeaways
- ActiveRecord querying: where/find_by answered "which rows". This course answers "in what order, and how many", on the same
ScratchArticleQscratch table. - Without an explicit
.order, row order isn't guaranteed. It's whatever the database finds convenient, and it can change between runs. .order(:column)generatesORDER BY column ASC; ascending is Rails' default direction.- This app's
Catalog::Lesson.orderedscope (order(:position)) uses this pattern so lessons render in the right sequence on every course page.
Keep going with lesson 2
.order(column: :desc): highest first
Passing a hash like views: :desc sorts highest first, the only way to get DESC in ActiveRecord.
A free account also gives you the quizzes, your progress and notes, and the discussion.