A convenção de engine que já está aqui

Prévia grátis 5 min de leitura

Quatro arquivos desta aplicação declaram uma convenção de engine do Rails. Vinte e três models recusam essa convenção. Esse é todo o ponto de partida.

A declaração

# app/models/catalog.rb
module Catalog
  def self.table_name_prefix
    "catalog_"
  end
end

Quatro namespaces fazem isso, Catalog, Community, Enrollment e Partners, e cada um define um prefixo. O Identity declara o módulo e nenhum prefixo.

O table_name_prefix é o idioma de engine do Rails. É o que o isolate_namespace configura para você, e serve para impedir que as tabelas de uma engine colidam com as da aplicação que a hospeda. Adotá-lo num monolito é adotar uma convenção de engine sem ter uma engine. Isso é razoável: uma tabela catalog_courses diz qual contexto é dono dela.

O que acontece na prática

USA o prefixo (1):
  Community::Comment -> community_comments

SOBRESCREVE (23):
  Catalog::Category           -> categories
  Catalog::Challenge          -> challenges
  Catalog::Course             -> courses
  Catalog::Lesson             -> lessons
  Catalog::Quiz               -> quizzes
  Catalog::QuizOption         -> quiz_options
  Catalog::QuizQuestion       -> quiz_questions
  Enrollment::Badge           -> badges
  Enrollment::Bookmark        -> bookmarks
  Enrollment::Enrollment      -> enrollments
  Enrollment::ExperiencePoint -> experience_points
  Enrollment::LessonCompletion -> lesson_completions
  Enrollment::LessonNote      -> lesson_notes
  Enrollment::Level           -> levels
  Enrollment::QuizAttempt     -> quiz_attempts
  Enrollment::UserBadge       -> user_badges
  Partners::ApiToken          -> partner_api_tokens
  Partners::CourseSponsorship -> partner_course_sponsorships
  Partners::HandoffNonce      -> partner_handoff_nonces
  Partners::Inquiry           -> partner_inquiries
  Partners::Partner           -> partners
  Partners::Referral          -> partner_referrals
  Partners::Role              -> partner_roles

Cada um desses vinte e três declara self.table_name explicitamente, e um nome de tabela explícito vence o prefixo.

Um model em vinte e quatro segue a convenção, e segue por não mencioná-la. O Community::Comment não tem a linha self.table_name, então o prefixo vale e a tabela é community_comments.

flowchart TB
  A["4 namespaces declaram table_name_prefix"] --> B["o idioma de engine do Rails, num monólito"]
  B --> C["23 models declaram self.table_name e sobrescrevem"]
  B --> D["1 model omite e fica com prefixo"]
  D --> E["Community::Comment -> community_comments"]
  C --> F["a convenção foi adotada, e recusada, um model por vez"]

Do que isso é evidência

Não é um bug. Todos esses vinte e três nomes estão corretos: courses, lessons e enrollments são bons nomes de tabela, e catalog_courses seria pior de digitar numa sessão do psql.

É evidência de uma convenção adotada sem uma decisão por trás. O enquadramento do curso de nível Pleno "Liderança: processo ADR" se aplica em cheio: as declarações de prefixo dizem o que fazer, nada diz por quê, e então quem escreveu cada model decidiu de novo, vinte e quatro vezes, e chegou à mesma resposta vinte e três vezes.

A única exceção também não parece uma discordância. O Community::Comment foi escrito em 30 de agosto, no mesmo dia dos quatro primeiros models do Partners, e todos esses declaram o nome da tabela. Nada no código diz por que este não declara.

Esse é o achado real: a nomenclatura atual das tabelas não é uma convenção. É o que sobrou de vinte e três decisões independentes e uma omissão.

As três opções honestas

Apagar as declarações de prefixo. Elas só têm efeito em um model de vinte e quatro, e no resto apenas levam quem lê a achar que as tabelas têm prefixo. Renomeie community_comments para comments e a base de código fica consistente.

Seguir as declarações. Apague as vinte e três linhas de self.table_name, escreva vinte e três migrações de renomeação, e toda tabela passa a anunciar o seu contexto. É caro, e deixa o esquema autodescritivo.

Deixar como está e registrar qual das duas é a verdade. Uma linha no MEMORY.md, um ADR: "as tabelas têm o nome do que guardam, não do contexto; as declarações de table_name_prefix são vestigiais."

Qualquer uma das três é melhor do que deixar isso sem registro, porque senão quem lê perde dez minutos toda vez que se pergunta se uma tabela tem prefixo, e a resposta é "em geral não, com uma exceção".

Esta aplicação ficou com a terceira opção em 2026-09-28. O MEMORY.md agora diz que as tabelas têm o nome do que guardam, que um model novo declara self.table_name e que as quatro declarações são vestigiais.

Por que isso abre um curso sobre engines

A pergunta por baixo é a que o curso inteiro faz: quanto do modelo de engine você quer, e quanto custa cada peça?

Esta aplicação pegou uma peça, o prefixo de tabela, e depois a rejeitou na prática. É uma resposta específica para uma pergunta específica, dada sem que ninguém enunciasse nenhuma das duas. A lição 2 mostra o resto do modelo.

Pontos-chave

  • Quatro namespaces declaram table_name_prefix, o idioma de engine do Rails para evitar colisão de tabelas.
  • Medido em 2026-09-28: 23 models sobrescrevem o prefixo com um self.table_name explícito; só 1 o segue, por omissão.
  • Nenhum dos vinte e três nomes está errado; é uma convenção adotada sem uma decisão por trás.
  • Três opções honestas: apagar as declarações, segui-las ou registrar qual é a verdade.
  • Hoje quem lê perde dez minutos sempre que se pergunta se as tabelas têm prefixo.
Aula 1 de 7 · grátis

Continue com a aula 2

O que uma engine de fato é

Uma engine é uma aplicação Rails dentro de outra; o isolate_namespace evita colisão de nomes, mas permite qualquer referência.

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

Digite para buscar...