.order: crescente, a menos que você diga o contrário

Prévia grátis 3 min de leitura

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 .order explícito, a ordem das linhas não é garantida. É a que o banco achar conveniente, e pode mudar entre execuções.
  • .order(:column) gera ORDER BY column ASC; crescente é a direção padrão do Rails.
  • O scope Catalog::Lesson.ordered deste app (order(:position)) usa esse padrão para as aulas aparecerem na sequência certa em toda página de curso.
Aula 1 de 7 · grátis

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.

Digite para buscar...