Melhor maneira de carregar o módulo / class da pasta lib no Rails 3?

Já que o último lançamento do Rails 3 não está mais carregando automaticamente módulos e classs da lib, qual seria a melhor maneira de carregá-los?

Do github:

A few changes were done in this commit: Do not autoload code in *lib* for applications (now you need to explicitly require them). This makes an application behave closer to an engine (code in lib is still autoloaded for plugins); 

A partir do Rails 2.3.9 , há uma configuração em config/application.rb na qual você pode especificar diretórios que contenham arquivos que você deseja carregar automaticamente.

De application.rb:

 # Custom directories with classs and modules you want to be autoloadable. # config.autoload_paths += %W(#{config.root}/extras) 
 # Autoload lib/ folder including all subdirectories config.autoload_paths += Dir["#{config.root}/lib/**/"] 

Fonte: Rails 3 Quicktip: Diretório do autoload lib incluindo todos os subdiretórios, evitando o carregamento lento

Por favor, lembre-se que os arquivos contidos na pasta lib só são carregados quando o servidor é iniciado. Se você quer o conforto para carregar automaticamente esses arquivos, leia: Rails 3 Quicktip: Auto recarrega as pastas lib no modo de desenvolvimento . Esteja ciente de que isso não se destina a um ambiente de produção, pois o recarregamento permanente desacelera a máquina.

A mágica do material de carregamento automático

Acho que a opção de controlar as pastas das quais o material de carregamento automático foi feito foi suficientemente coberta em outras respostas. No entanto, no caso de alguém estar tendo problemas com o carregamento, embora tenham seus caminhos de autoload modificados conforme a necessidade, essa resposta tenta explicar qual é a mágica por trás dessa coisa de autoload.

Então, quando se trata de carregar coisas de subdiretórios, há uma pegadinha ou uma convenção que você deve estar ciente. Às vezes, a mágica Ruby / Rails (desta vez principalmente Rails) pode dificultar a compreensão de por que algo está acontecendo. Qualquer módulo declarado nos caminhos de carregamento automático será carregado apenas se o nome do módulo corresponder ao nome do diretório pai. Então, caso você tente colocar na lib/my_stuff/bar.rb algo como:

 module Foo class Bar end end 

Não será carregado automaticamente. Então, novamente, se você renomear o diretório pai para foo , hospedando seu módulo no caminho: lib/foo/bar.rb Estará lá para você. Outra opção é nomear o arquivo que você deseja carregar automaticamente pelo nome do módulo. Obviamente, só pode haver um arquivo com esse nome. Caso você precise dividir suas coisas em muitos arquivos, é claro que você pode usar esse arquivo para exigir outros arquivos, mas eu não recomendo isso, porque quando você está no modo de desenvolvimento e modifica esses outros arquivos, o Rails não é capaz de automagicamente recarregá-los para você. Mas se você realmente quiser, você pode ter um arquivo pelo nome do módulo que, em seguida, especifica os arquivos reais necessários para usar o módulo. Então você poderia ter dois arquivos: lib/my_stuff/bar.rb e lib/my_stuff/foo.rb e o primeiro sendo o mesmo que acima e o último contendo uma única linha: require "bar" e isso funcionaria da mesma forma.

PS Sinto-me obrigado a adicionar mais uma coisa importante. Ultimamente, sempre que eu quero ter algo no diretório lib que precisa ser carregado automaticamente, eu costumo começar a pensar que se isso é algo que eu estou realmente desenvolvendo especificamente para este projeto (o que geralmente é, pode algum dia se transformar em um trecho “estático” de código usado em muitos projetos ou em um submódulo git, etc., nesse caso, definitivamente deve estar na pasta lib), então talvez seu lugar não esteja na pasta lib. Talvez devesse estar em uma subpasta na pasta do aplicativo. Tenho a sensação de que essa é a nova maneira de fazer as coisas. Obviamente, a mesma magia está no trabalho, sempre que você fizer o autoload de caminhos, coloque suas coisas de modo que seja bom para essas coisas. De qualquer forma, este é apenas o meu pensamento sobre o assunto. Você é livre para discordar. 🙂


UPDATE: Sobre o tipo de magia ..

Como severin salientou em seu comentário, o núcleo “autoload um mecanismo de módulo” com certeza faz parte do Ruby, mas o material de caminhos de autoload não é. Você não precisa do Rails para fazer o autoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar") . E quando você tentaria fazer referência ao módulo Foo pela primeira vez, ele seria carregado para você. No entanto, o que o Rails faz é nos dar uma maneira de tentar carregar coisas automagicamente a partir de pastas registradas e isso foi implementado de tal forma que ele precisa assumir algo sobre as convenções de nomenclatura. Se não tivesse sido implementado assim, toda vez que você fizer referência a algo que não está atualmente carregado, ele terá que passar por todos os arquivos em todas as pastas de autoload e verificar se algum deles contém o que você estava tentando referenciar. Isso, por sua vez, derrotaria a ideia de autoloading e autoreloading. No entanto, com essas convenções em vigor, ele pode deduzir do módulo / class que você está tentando carregar onde isso pode ser definido e apenas carregá-lo.

Aviso: se você quiser carregar o ‘monkey patch’ ou ‘open class’ da sua pasta ‘lib’, não use a abordagem ‘autoload’ !!!

  • Abordagem ” config.autoload_paths “: só funciona se você estiver carregando uma class definida apenas em um lugar. Se alguma class já tiver sido definida em algum outro lugar, você não poderá carregá-la novamente por essa abordagem.

  • Abordagem ” config / initializer / load_rb_file.rb “: sempre funciona! seja qual for a class alvo é uma nova class ou uma “class aberta” ou “patch de macaco” para a class existente, sempre funciona!

Para mais detalhes, consulte: https://stackoverflow.com/a/6797707/445908

Muito parecido, mas acho que isso é um pouco mais elegante:

 config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/"] 

No meu caso eu estava tentando simplesmente carregar um arquivo diretamente sob o diretório lib.

Dentro de application.rb …

 require '/lib/this_file.rb' 

não estava funcionando, mesmo no console e, em seguida, quando eu tentei

 require './lib/this_file.rb' 

e rails carrega o arquivo perfeitamente.

Eu ainda sou bem noob e não tenho certeza porque isso funciona, mas funciona. Se alguém quiser me explicar, eu agradeço: espero que isso ajude alguém de qualquer maneira.

Eu tive o mesmo problema. Aqui está como eu resolvi isso. A solução carrega o diretório lib e todos os subdiretórios (não apenas o direto). Claro que você pode usar isso para todos os diretórios.

 # application.rb config.autoload_paths += %W(#{config.root}/lib) config.autoload_paths += Dir["#{config.root}/lib/**/"] 

config.autoload_paths não funciona para mim. Eu resolvo de outra maneira

Ruby on rails 3 não faz o código de recarregamento automático (autoload) da pasta / lib. Eu resolvo colocando dentro do ApplicationController

 Dir["lib/**/*.rb"].each do |path| require_dependency path end 

Se apenas alguns arquivos precisarem de access aos módulos no lib, basta include uma instrução require nos arquivos que precisam dela. Por exemplo, se um modelo precisar acessar um módulo, adicione:

 require 'mymodule' 

no topo do arquivo model.rb.

Existem vários motivos pelos quais você pode ter problemas ao carregar da lib – veja aqui para mais detalhes – http://www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classs-in-production/

  • corrigir caminho de carregamento automático
  • threadsafe relacionado
  • nomeação relacionada

A partir do Rails 5 , recomenda-se colocar a pasta lib no diretório do aplicativo ou criar outros espaços de nomes significativos para a pasta como services , presenters , features , etc. e colocá-la no diretório do aplicativo para carregamento automático por rails.

Por favor, verifique também este link de discussão do GitHub .

Soletre o nome do arquivo corretamente.

A sério. Eu lutei com uma aula por uma hora porque a class era Governance :: ArchitectureBoard e o arquivo estava em lib / governance / architecture_baord.rb (O e A transpostos em “board”)

Parece óbvio em retrospecto, mas foi o diabo rastreando isso. Se a class não estiver definida no arquivo no qual o Rails espera que esteja, baseando-se no nome da class, ela simplesmente não a encontrará.