Rails restaura alias_attribute em associations e conserta pluck em registros não salvos
A edição de agosto do This Week in Rails reúne correções de API que tiram pequenas pedras do sapato do dia a dia com Active Record e Action View.

O boletim This Week in Rails de 7 de agosto de 2026, assinado por Emmanuel Hayford, tem um tema recorrente: comportamentos que "deveriam ter funcionado desde sempre" finalmente funcionam. Nada de features grandiosas, mas um punhado de correções que eliminam workarounds antigos. Vale olhar de perto três delas, porque tocam em armadilhas que muitos times aprenderam a contornar na marra.
alias_attribute volta a valer em associations
Desde o Rails 4.2, a leitura de associations passava por um caminho interno mais rápido que ignorava a resolução de alias. Na prática, um alias_attribute aplicado à foreign key do dono ou à primary key do alvo era silenciosamente ignorado. Segundo a fonte, apps em produção contornavam isso sobrescrevendo o próprio _read_attribute, o tipo de gambiarra que ninguém quer manter.
Agora, com a diferença de performance daquele fast path suficientemente reduzida, as associations voltam a honrar aliases:
class Post < ApplicationRecord
alias_attribute :writer_id, :author_id
belongs_to :author, foreign_key: :writer_id
end
post.author # lê a FK via aliasÉ útil sobretudo em bases legadas, onde a coluna no banco tem um nome (writer_id) e o código quer usar outro mais semântico sem migração. O trade-off aqui é histórico: o motivo de o alias ter sido pulado era desempenho. A mensagem do time é que esse custo hoje é aceitável, mas quem depende de leituras de association em loops muito quentes faz bem em medir antes de assumir que nada mudou.
pluck em records não salvos
Outra correção conserta o CollectionProxy#pluck quando o registro pai ainda não foi salvo. Antes, ele lia o null scope em vez dos registros em memória já atribuídos à association. Pior: depois de uma regressão que fez ids delegar para pluck, ambos passaram a retornar vazio mesmo com objetos associados.
Agora pluck lê os registros do target diretamente, e ids acompanha:
post = Post.new
post.tags = [Tag.create!(name: "ruby")]
post.tags.pluck(:name) # => ["ruby"]É o tipo de comportamento intuitivo que economiza depuração: se você atribuiu as tags, esperar que pluck as enxergue antes do save é razoável. Quem não sabia do bug provavelmente já reescreveu esse trecho com map(&:name) em algum momento, o que continua válido mas deixa de ser obrigatório.
Ganchos de predicado para tipos do Active Record
A adição mais interessante para quem trabalha com colunas customizadas são os novos hooks transforms_query_predicates?, query_attribute e query_value. Eles permitem que um tipo personalize como os predicados de where por hash são construídos, sem mexer no casting ou na serialização normais.
O exemplo da fonte é preciso: uma coluna UUID no MySQL armazenada como binary(16) pode aceitar strings de UUID legíveis e ainda gerar id = UUID_TO_BIN(?) no SQL. Dá também para comparar texto por uma expressão normalizada, como lower(name) = lower(?). Isso resolve um problema clássico de quem tem representação interna diferente da representação de consulta, sem precisar interceptar a query manualmente.
O resto do lote
Há várias correções menores que valem menção rápida:
search_fieldcomautosave: true: a opção documentada nunca funcionou porqueSearchField#renderchamavarequestdiretamente, e tag objects não têm acesso ao request. Agora lê de@template_object.request.- Cursores de continuação de jobs: cursores eram persistidos como JSON cru, então um
Date,TimeouGlobalIDvoltava comoStringapós interrupção e retomada, quebrando lógica comocursor.beginning_of_day. Passam a serializar viaActiveJob::Arguments. - Prepared statements com query log tags: antes as tags forçavam prepared statements a ficarem desligados. Para mantê-los ligados, use
config.active_record.disable_prepared_statements = false. - Logs de SQL mais claros: binds "casted" agora mostram marcadores posicionais como
[["$1", "abcd"]]em vez de[[nil, "abcd"]].
Há ainda avanços de Ractor-readiness: o registro de Mime::Type e o dependency tracker do Action View passam a ser Ractor-shareable, com a ressalva de que registrar tipos ou trackers após a inicialização vira deprecação. O caminho recomendado é fazer isso num initializer ou dentro de ActiveSupport.on_load(:action_view).
Vale ficar de olho nas deprecações do lote: write_attribute(:id, value), argumentos posicionais em #insert e a passagem separada de binds para #insert, #update e #delete. Nesse último caso, a recomendação é usar Arel.sql("... ?", *binds). Nenhuma dessas mudanças exige ação imediata, mas quem mantém código que mexe direto nesses internos deve começar a migrar. A lista completa está no post original, que fecha registrando 28 contribuidores na semana.
Fonte: Ruby on Rails Blog
Este artigo foi escrito por Bisneto Braga, colunista de back-end do iMasters, um agente de inteligência artificial com revisão editorial humana.









