Rails 5: Carregar arquivos lib na produção

128

Atualizei um dos meus aplicativos do Rails 4.2.6 para o Rails 5.0.0. o Guia de atualização diz que o recurso Carregamento automático agora está desativado na produção por padrão.

Agora sempre recebo um erro no meu servidor de produção, pois carrego todos os arquivos lib com o carregamento automático no application.rbarquivo.

module MyApp
    class Application < Rails::Application
        config.autoload_paths += %W( lib/ )
    end
end

Por enquanto, eu configurei o config.enable_dependency_loadingpara, truemas me pergunto se existe uma solução melhor para isso. Deve haver um motivo para o carregamento automático estar desativado na produção por padrão.

Tobias
fonte
coisa louca e os documentos ainda dizem para você fazer o auto_load. Fiquei muito confuso sobre o que está acontecendo de errado no ambiente de produção para um novo aplicativo. E desde que comecei a aprender com o Rails 5, não li o guia de migração. I apresentou uma questão doc para obter espero que isto resolvido: github.com/rails/rails/issues/27268
akostadinov
1
incrivelmente, eu tenho dois arquivos em libdir, um arquivo é facilmente disponível em tempo de execução, mas outro tem de ser requerida manualmente: D
ilusionista
@ Tobias Com que solução você acabou?
geoboy
@geoboy Eu agrupo o código (como Validators) em pastas diretamente no diretório app /, já que o código é carregado automaticamente.
Tobias
trata-se de caminho de arquivo adequado e definição de classe aqui é o trabalho para mim no Rails 5.2: Caminho do arquivo: app/services/paylinx/paylinx_service.rbDefinição de classe: module Paylinx class PaylinxService end end. Eu tentei essas autoload_pathscoisas. não funciona para mim.
NamNamNam 27/01/19

Respostas:

161

Minha lista de alterações depois de passar para o Rails 5:

  1. Coloque o libdiretório appporque todo o código dentro do aplicativo é carregado automaticamente no dev e ansiosamente carregado no prod e, o mais importante, é carregado automaticamente no desenvolvimento, para que você não precise reiniciar o servidor toda vez que fizer alterações.
  2. Remova todas as requireinstruções que apontam para suas próprias classes, libporque todas elas são carregadas automaticamente de qualquer maneira, se a nomeação de arquivos / diretórios estiver correta e, se você deixar as requireinstruções, elas poderão interromper o carregamento automático. Mais informações aqui
  3. Defina config.eager_load = trueem todos os ambientes para ver os problemas de carregamento de código ansiosamente no dev.
  4. Use Rails.application.eager_load!antes de jogar com os threads para evitar erros de "dependência circular".
  5. Se você tiver alguma extensão ruby ​​/ rails, deixe esse código dentro do libdiretório antigo e carregue-o manualmente no inicializador. Isso garantirá que as extensões sejam carregadas antes de sua lógica adicional, que pode depender dela:

    # config/initializers/extensions.rb
    Dir["#{Rails.root}/lib/ruby_ext/*.rb"].each { |file| require file }
    Dir["#{Rails.root}/lib/rails_ext/*.rb"].each { |file| require file }
Lev Lukomsky
fonte
8
Então, como alguém usa a libpasta agora? Quero dizer, mover o libdiretório para o appdiretório parece uma solução alternativa.
Martin Svoboda
3
/app/lib/colocou um arquivo / classe e NÃO é o carregamento automático. testado em trilhos 5.1, novo projeto
Tim Kretschmer
29
Vale a pena notar que você precisa parar a primavera. Mudei tudo para app / lib / e perdi um pouco de tempo imaginando por que ainda não conseguia usar minhas classes no console. Spring Stop ftw :)
jacklin 13/08/17
1
Para onde iria a seguinte linhaRails.application.eager_load!
Steven Aguilar
1
Isso pode funcionar, mas não é a melhor solução. A estrutura da pasta também é semântica. As coisas libtêm uma proximidade percebida diferente do projeto e as coisas no appdiretório. Várias das outras respostas são melhores que esta.
CWitty
84

Eu apenas usei, em config.eager_load_pathsvez de config.autoload_pathsmencionar akostadinov no comentário do github: https://github.com/rails/rails/issues/13142#issuecomment-275492070

# config.autoload_paths << Rails.root.join('lib')
config.eager_load_paths << Rails.root.join('lib')

Trabalha no ambiente de desenvolvimento e produção.

Graças Johan para a sugestão de substituir #{Rails.root}/libcom Rails.root.join('lib')!

Michał Zalewski
fonte
3
Funciona como um encanto. Eu não gostei da sintaxe, então mudei para config.eager_load_paths << Rails.root.join('lib').
3limin4t0r
2
Para mim, essa foi a melhor resposta. Meu projeto começou no Rails 5.2 a partir do zero e a pasta / lib ainda foi criada fora da pasta / app. Não vi uma boa razão para mudar isso.
Samir Haddad
1
Sim, isso funciona! Parece que os desenvolvedores do Rails realmente gostam de causar problemas no carregamento da biblioteca: D até a próxima!
Damien Roche
Em config.eager_load_paths += [Rails.root.join('lib')]vez disso, o To Rails 5.2 usa porque config.eager_load_pathsé uma matriz congelada
William Wong Garay
@WilliamWongGaray config.eager_load_paths é somente leitura quando você tenta modificá-lo no inicializador. Quando você adiciona caminhos, application.rbele funciona usando os dois métodos.
Michał Zalewski
31

O carregamento automático está desativado no ambiente de produção devido à segurança do encadeamento. Obrigado a @ forелёный pelo link.

Resolvi esse problema armazenando os arquivos lib em uma libpasta no meu appdiretório, conforme recomendado no Github . Todas as pastas da apppasta são carregadas pelo Rails automaticamente.

Tobias
fonte
6
Se você não quiser explorar um longo tópico de discussão no Github, pode encontrar uma explicação detalhada aqui: coletivoidea.com/blog/archives/2016/07/22/…
Ernest
7
Eu usei config.eager_load_paths << "#{Rails.root}/lib", é melhor o IMO seguir a estrutura de aplicativos recomendada para trilhos.
akostadinov 5/12/16
2
Colocar a lib in app/libé recomendado pelos membros do rails github.com/rails/rails/issues/13142#issuecomment-275549669
eXa
4
Isso arruina completamente qual é o objetivo lib. Eu esperaria que o amor de mãe ou o DHH entrassem em cena. Enquanto isso, eu (pessoalmente) recomendo seguir a resposta de @Lev Lukomsky.
Josh Brody
@ JoshBrody Minha opinião agora é que você não precisa do /libdiretório. As bibliotecas de terceiros são na maioria das vezes gemas e, se não, deve haver uma gema criada. Para outros arquivos, eu crio pastas específicas no /appdiretório. Por exemplo validators.
Tobias
22

Deve haver um motivo para o carregamento automático estar desativado na produção por padrão.

Aqui está uma longa discussão sobre esse problema. https://github.com/rails/rails/issues/13142

Зелёный
fonte
1
Essa discussão é a melhor fonte de informações sobre o assunto, apesar de uma longa leitura.
Jason
12

Isso permite que a lib seja carregada automaticamente e também funciona no ambiente de produção.

PS: Eu mudei minha resposta, agora ela adiciona os dois caminhos de carregamento automático, independentemente do ambiente, para permitir o trabalho em ambientes personalizados também (como estágio)

# config/initializers/load_lib.rb
...
config.eager_load_paths << Rails.root.join('lib')
config.autoload_paths << Rails.root.join('lib')
...
srghma
fonte
2
Você poderia expandir por que isso corrige o problema?
precisa saber é o seguinte
@ Stuart.Sklinar isso permite ter auto-carregamento de lib e também funciona no ambiente de produção. PS Eu mudei minha resposta, agora ele acrescenta que ambos eager- um caminhos carregar automaticamente, independentemente do meio ambiente, para permitir o trabalho em ambientes personalizados também (como estágio)
srghma
1
Você poderia expandir (em sua resposta)? As respostas apenas de código não ajudam ninguém a entender por que isso deve ser feito "dessa maneira" - devo acrescentar que não sou um desenvolvedor Ruby, apenas ajudando a esclarecer o SO. Adicionar algum comentário a uma "resposta apenas de código" forneceria algum contexto real.
precisa saber é o seguinte
1
@ Stuart.Sklinar sure
srghma
6

Apenas altere config.autoload_paths para config.eager_load_paths no arquivo config / application.rb. Como no Rails 5 o carregamento automático é desativado para o ambiente de produção por padrão. Para mais detalhes, siga o link .

 #config.autoload_paths << "#{Rails.root}/lib"
  config.eager_load_paths << Rails.root.join('lib')

Funciona para o desenvolvimento e produção do ambiente.

Jitendra Rathor
fonte
4

Em certo sentido, aqui está uma abordagem unificada no Rails 5 para centralizar as configurações de carregamento rápido e automático, ao mesmo tempo em que adiciona o caminho de carregamento automático necessário sempre que o carregamento rápido estiver configurado, caso contrário não será possível funcionar corretamente:

# config/application.rb
...
config.paths.add Rails.root.join('lib').to_s, eager_load: true

# as an example of autoload only config
config.paths.add Rails.root.join('domainpack').to_s, autoload: true
...
pocheptsov
fonte
2

Para alguém que lutou com isso como eu, não basta colocar um diretório abaixo app/. Sim, você receberá o carregamento automático, mas não o necessário , o que exige que as convenções de espaço para nome sejam cumpridas .

Além disso, o uso do inicializador para carregar o nível raiz antigo libimpedirá o recurso de recarregamento durante o desenvolvimento.

Abdullah Barrak
fonte
0

Mover a pasta lib para o aplicativo ajudou a resolver um problema, minha API do Twitter não funcionava na produção. Eu tinha "constante TwitterApi não inicializado" e minha API do Twitter estava na minha pasta lib. Eu tinha config.autoload_paths += Dir["#{Rails.root}/app/lib"]no meu application.rb, mas não funcionou antes de mover a pasta.

Isso fez o truque

Laurie
fonte
-6

para resumir a resposta de Lev: mv lib appbastava ter todo o meu libcódigo carregado / recarregado automaticamente.

(rails 6.0.0beta3, mas também deve funcionar bem no rails 5.x)

localhostdotdev
fonte