.pick: o atalho de uma linha só do .pluck

Prévia grátis 3 min de leitura

De onde isto continua

A aula "SELECT & FROM no Rails", de SQL puro: SELECT e FROM, tratou do básico. .select(:name, :email) devolve objetos de model só com as colunas escolhidas preenchidas, e uma coluna não selecionada volta como nil, igual a um NULL do banco. .pluck(:name) pula a criação de models e devolve um array simples. Uma tabela naquela aula mostrou quando usar .pluck, .select ou .exists?. Querying ActiveRecord: order usou .pluck o tempo todo para imprimir resultados sem ruído. Este curso vai além: .pick, a diferença no número de consultas entre .pluck e .map(&:attr), .pluck através de um join, distinct.pluck e uma armadilha própria do concern Translatable deste app.

A pergunta que .pick responde: um valor, não uma lista

"Qual é o slug do curso de menor position?" precisa de uma string, não de um array. .pluck sempre devolve um array, mesmo quando só uma linha importa:

Catalog::Course.order(:position).pluck(:slug).first
# => "computer-architecture"

Funciona, mas busca o slug de todo curso que bate e depois joga fora tudo menos o primeiro, no Ruby. .pick faz o mesmo trabalho sem desperdício:

Catalog::Course.order(:position).pick(:slug)
# => "computer-architecture"

.pick roda LIMIT 1, .pluck.first não

Este é o SQL que cada um manda, na tabela Catalog::Course deste app:

Course.order(:position).pick(:slug)
SELECT "courses"."slug" FROM "courses" ORDER BY "courses"."position" ASC LIMIT 1

Course.order(:position).pluck(:slug).first
SELECT "courses"."slug" FROM "courses" ORDER BY "courses"."position" ASC

.pick põe LIMIT 1 no SQL, então o banco para depois da primeira linha. .pluck(:slug).first não tem LIMIT. Ele traz o slug de todo curso (algumas centenas neste catálogo) pela rede, monta um array desse tamanho no Ruby e só então chama .first para ficar com um. Numa tabela pequena você não percebe; numa grande, .pick é o que escala.

.pick é construído sobre .pluck

O log do Rails rotula uma chamada .pick como Course Pluck, não Course Pick. Não é erro de exibição. Por dentro, .pick é .limit(1).pluck(*columns).first, o mesmo mecanismo que esta aula descreveu à mão. Isso explica o rótulo, e significa que .pick herda o que .pluck faz: sem objetos de model, valores crus de volta e várias colunas aceitas do mesmo jeito.

Várias colunas também funcionam

Catalog::Course.order(:position).pick(:slug, :level)
# => ["computer-architecture", "intern"]

É o formato de várias colunas do .pluck (um array, não um hash) para a única linha em que .pick para. É a mesma regra de um array de valores por linha que "SELECT & FROM no Rails" mostrou para .pluck(:name, :email), reduzida a uma linha só.

Pontos-chave

  • "SELECT & FROM no Rails" tratou da armadilha do nil em .select e do array simples de .pluck. Este curso segue para .pick, número de consultas, joins e uma armadilha do Translatable.
  • .pick(:column) devolve um único valor de uma linha, não um array. .pluck(:column).first imita isso descartando tudo depois do primeiro elemento.
  • .pick acrescenta LIMIT 1 ao SQL, e o banco para depois de uma linha. .pluck(:column).first não tem LIMIT e busca a coluna de toda linha que bate antes de o Ruby ficar com a primeira.
  • .pick é .limit(1).pluck(*columns).first por dentro, por isso o log do Rails o rotula como "Pluck". Ele mantém o comportamento de .pluck: sem objetos de model, e um array para várias colunas.
Aula 1 de 7 · grátis

Continue com a aula 2

.pluck vs .map(&:attr): o que custa uma query

.pluck estreita o SELECT em relations não carregadas, lê da memória nas carregadas e sempre consulta para expressões SQL.

Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.

Digite para buscar...