Tenho uma pasta Rails com dois arquivos:
app/hub_spot/client.rb:
module HubSpot
class Client
app/hub_spot/create_contact_form.rb:
module HubSpot
class CreateContactForm
quando executo a verificação zeitwerk recebo:
expected file app/hub_spot/client.rb to define constant Client, but didn't
se eu adicionar:
config.autoload_paths << Rails.root.join("app/hub_spot")
config.eager_load_paths << Rails.root.join("app/hub_spot")
então recebo um novo erro:
expected file app/hub_spot/create_contact_form.rb to define constant CreateContactForm, but didn't
parece reclamar sobre ambos os arquivos de forma diferente? Tem alguma maneira de dizer ao Zeitwerk para olhar a pasta para o nome do módulo?
O Rails usa uma configuração de autoloader bem peculiar por motivos históricos/de preguiça. Ele é realmente mais orientado em torno de apenas organizar constantes de nível superior por propósito do que coisas chatas como encapsulamento.
Cada subdiretório do
app
diretório é automaticamente adicionado como um diretório raiz no Zeitwerk. Os diretórios raiz são onde o Zeitwork espera que as constantes de nível superior sejam encontradas e são ignorados ao resolver um caminho de arquivo em uma constante. O Rails ainda usa os termosautoloading_paths
eeager_load_paths
que é um resquício do autoloader clássico usado até o Rails 6, que são aproximadamente equivalentes.Assim, se você mover seu arquivo para
app/foo/hub_spot/client.rb
o Zeitwork, não terá problemas em encontrá-lo. Note que o nome da pasta de nível raiz é, na verdade, inconsequente (exceto para nós, humanos).Você pode comparar isso com a configuração típica de uma gem, que tem apenas um único diretório raiz (
lib
) e onde se espera que o código esteja aninhado no módulo e na pasta com o nome da gem.Embora você possa adicionar o
app
próprio diretório como uma raiz de carregamento automático, eu ficaria atento a possíveis bugs.Na verdade, a única razão para colocar código
app
(exceto a expectativa de outros desenvolvedores) é que você deseja usar a configuração do carregador automático do Rails, então aceite a estranheza e adicione outro nível de aninhamento de diretório para que seja pelo menos consistentemente estranho.Você também pode configurar o Zeitwerk para carregar seu código e
lib/my_namespace
espelhar como as gems são configuradas (o que é bem menos peculiar).Não. Ele está dizendo que espera que as constantes sejam definidas no nível superior, já que o caminho do arquivo da perspectiva dele é apenas
/create_contact_form.rb
. Ele está apenas verificando arquivos diferentes.config.autoload_paths << Rails.root.join("app/hub_spot")
é completamente redundante, pois isso acontece por padrão de qualquer maneira.Ver:
Corrigir o problema de namespace Sua situação atual:
aplicativo/hub_spot/client.rb aplicativo/hub_spot/create_contact_form.rb
Esses arquivos estão dentro de app/hub_spot/, então o Zeitwerk os espera dentro do módulo HubSpot. Mas o Zeitwerk não deduz o módulo HubSpot do nome da pasta em si — você deve especificá-lo explicitamente.
Solução: Reorganize a estrutura do arquivo ou as definições do módulo Opção 1: Mova a pasta para app/lib/ ou app/models/ O Zeitwerk carrega diretórios em app/ (como modelos, controladores, etc.) automaticamente, mas app/hub_spot/ não é um deles por padrão.
Em vez disso, coloque sua pasta em app/lib/hub_spot/ e inclua: