.order: crescente, a menos que você diga o contrário
Onde o curso de where/find_by parou
Querying ActiveRecord: where passou sete aulas numa pergunta: quais linhas voltam. .where e find_by estreitam uma tabela para as linhas que atendem a uma condição, e aquele curso rodou todos os exemplos na tabela de rascunho ScratchArticleQ (title, category, published, views). Este curso faz outra pergunta sobre as mesmas linhas: em que ordem elas voltam, e quantas você quer? Isso é .order e .limit, e os dois se combinam com tudo o que o curso anterior ensinou.
As mesmas linhas, sem ordem garantida
ScratchArticleQ.where(published: true)
Isto devolve todo artigo publicado, e nada na chamada fala de ordem. O PostgreSQL pode devolver as linhas na ordem que for conveniente, muitas vezes a ordem de armazenamento numa tabela pequena sem índice. Isso é detalhe de implementação, não uma promessa. Duas execuções da mesma consulta podem voltar em ordens diferentes, principalmente depois de um update ou de um vacuum. Uma view que mostra artigos "na ordem que o banco quiser" tem um bug que aparece na primeira vez que a organização interna do banco muda.
.order(:column): uma coluna, crescente
ScratchArticleQ.order(:views)
# SQL: SELECT "scratch_articles_q".* FROM "scratch_articles_q"
# ORDER BY "scratch_articles_q"."views" ASC
A tabela de rascunho tem seis linhas com views de 5, 12, 15, 40, 90 e 100. Um único símbolo passado para .order gera ORDER BY column ASC: crescente, menor valor primeiro. É a direção padrão do Rails, então você nunca precisa digitar 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) vem primeiro e "Rails Tips" (100 views) vem por último. Nenhuma surpresa depois de ver uma vez. O que importa é o modelo mental errado que isso substitui: SQL sem ORDER BY não usa a ordem de inserção por padrão.
Deste app: Catalog::Lesson.ordered
O model Catalog::Lesson deste projeto tem um scope que faz isso, e ele roda toda vez que a página de um curso carrega:
# app/models/catalog/lesson.rb
scope :ordered, -> { order(:position) }
Toda aula tem uma coluna inteira position. Catalog::Lesson.ordered garante que a aula 3 de um curso sempre aparece depois da aula 2, seja qual for a ordem em que o PostgreSQL devolve as linhas. O scope for_course, que encadeia where(course_id: ...).ordered, garante o mesmo. Sem esse .order(:position), a lista de aulas de um curso estaria a uma mudança de armazenamento de mostrar "Variables" antes de "Setting Up Your Editor".
Símbolos, strings e aspas
.order(:views) e .order("views") devolvem as mesmas linhas aqui, mas o SQL é diferente. Com um símbolo, o ActiveRecord qualifica a coluna com a tabela e põe aspas: ORDER BY "scratch_articles_q"."views" ASC, a mesma convenção do .where. Uma string entra no SQL como foi escrita: ORDER BY views. As aspas permitem a uma tabela ter uma coluna chamada order sem o PostgreSQL tropeçar na palavra reservada. Por isso a forma com símbolo (ou hash) é o padrão mais seguro.
Pontos-chave
- Querying ActiveRecord: where respondeu "quais linhas". Este curso responde "em que ordem, e quantas", na mesma tabela de rascunho
ScratchArticleQ. - Sem um
.orderexplícito, a ordem das linhas não é garantida. É a que o banco achar conveniente, e pode mudar entre execuções. .order(:column)geraORDER BY column ASC; crescente é a direção padrão do Rails.- O scope
Catalog::Lesson.ordereddeste app (order(:position)) usa esse padrão para as aulas aparecerem na sequência certa em toda página de curso.
Continue com a aula 2
.order(column: :desc): maior primeiro
Um hash como views: :desc ordena do maior para o menor, a única forma de obter DESC.
Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.