Il modo migliore per caricare modulo / class dalla cartella lib in Rails 3?

Dal momento che l’ultima versione di Rails 3 non sta caricando automaticamente moduli e classi da lib, quale sarebbe il modo migliore per caricarli?

Da 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 partire da Rails 2.3.9 , esiste un’impostazione in config/application.rb in cui è ansible specificare le directory che contengono i file che si desidera caricare automaticamente.

Da 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/**/"] 

Origine: Rails 3 Quicktip: Autoload lib directory che include tutte le sottodirectory, evitare il caricamento lazy

Si prega di notare che i file contenuti nella cartella lib vengono caricati solo all’avvio del server. Se si desidera il comfort per caricare automaticamente questi file, leggere: Rails 3 Quicktip: Auto ricarica le cartelle lib in modalità di sviluppo . Essere consapevoli del fatto che questo non è inteso per un ambiente di produzione poiché il ricarico permanente rallenta la macchina.

La magia del caricamento automatico di cose

Penso che l’opzione che controlla le cartelle da cui viene eseguito il caricamento automatico sia stata sufficientemente trattata in altre risposte. Tuttavia, nel caso in cui qualcun altro abbia problemi con le cose caricate sebbene abbiano modificato i loro percorsi di caricamento automatico come richiesto, allora questa risposta prova a spiegare qual è la magia dietro questa cosa del caricamento automatico.

Quindi, quando si tratta di caricare materiale da sottodirectory, è necessario conoscere un accordo o una convenzione. A volte la magia Ruby / Rails (questa volta principalmente Rails) può rendere difficile capire perché qualcosa stia accadendo. Qualsiasi modulo dichiarato nei percorsi di caricamento automatico verrà caricato solo se il nome del modulo corrisponde al nome della directory padre. Quindi nel caso si provi a inserire in lib/my_stuff/bar.rb qualcosa del tipo:

 module Foo class Bar end end 

Non verrà caricato automaticamente. Poi di nuovo se rinominate la dir padre in foo quindi ospitate il vostro modulo sul percorso: lib/foo/bar.rb Sarà lì per te. Un’altra opzione è denominare il file che si desidera caricare automaticamente dal nome del modulo. Ovviamente ci può essere solo un file con quel nome allora. Nel caso in cui abbiate bisogno di dividere i vostri file in molti file, potreste ovviamente usare quel file per richiedere altri file, ma io non lo consiglio, perché quando si è in modalità sviluppo e si modificano questi altri file, Rails non è in grado di automatizzare ricaricalo per te. Ma se davvero vuoi che tu possa avere un file con il nome del modulo che poi specifica i file reali richiesti per usare il modulo. Quindi potresti avere due file: lib/my_stuff/bar.rb e lib/my_stuff/foo.rb e il primo è lo stesso di sopra e quest’ultimo contiene una singola riga: require "bar" e funzionerebbe lo stesso.

PS Mi sento in dovere di aggiungere un’altra cosa importante. Di recente, ogni volta che voglio avere qualcosa nella directory lib che deve essere caricato automaticamente, tendo a pensare che se questo è qualcosa che sto effettivamente sviluppando specificamente per questo progetto (che di solito è, potrebbe un giorno trasformarsi in uno snippet “statico” di codice usato in molti progetti o in un sottomodulo git, ecc. nel qual caso dovrebbe essere sicuramente nella cartella lib) quindi forse la sua posizione non è affatto nella cartella lib. Forse dovrebbe trovarsi in una sottocartella sotto la cartella dell’app. Ho la sensazione che questo sia il modo in cui le nuove binari fanno le cose. Ovviamente, la stessa magia è all’opera ovunque nei percorsi di auto-caricamento tu metti le tue cose così va bene a queste cose. Ad ogni modo, questo è solo il mio pensiero sull’argomento. Sei libero di non essere d’accordo. 🙂


AGGIORNAMENTO: sul tipo di magia ..

Come severin ha sottolineato nel suo commento, il core “autoload a module mechanism” è sicuramente parte di Ruby, ma la roba dei percorsi di caricamento automatico non lo è. Non hai bisogno di Rails per fare autoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar") . E quando proverai a fare riferimento al modulo Foo per la prima volta, verrà caricato per te. Tuttavia, ciò che Rails fa è che ci dà un modo per provare e caricare roba automaticamente dalle cartelle registrate e questo è stato implementato in modo tale che ha bisogno di assumere qualcosa sulle convenzioni di denominazione. Se non fosse stato implementato in questo modo, ogni volta che fai riferimento a qualcosa che non è attualmente caricato, dovrebbe passare attraverso tutti i file in tutte le cartelle di caricamento automatico e controllare se qualcuno di essi contiene ciò che stavi cercando di fare riferimento. Ciò a sua volta vanificherebbe l’idea di autoloading e autoreloading. Tuttavia, con queste convenzioni in atto, è ansible dedurre dal modulo / class il tentativo di caricare dove potrebbe essere definito e solo caricarlo.

Attenzione: se vuoi caricare la ‘patch scimmia’ o ‘class aperta’ dalla tua cartella ‘lib’, non usare l’ approccio ‘autoload’ !!!

  • approccio ” config.autoload_paths “: funziona solo se stai caricando una class che ha definito solo in UN posto. Se qualche class è già stata definita da qualche altra parte, non è ansible caricarla di nuovo con questo approccio.

  • approccio ” config / initializer / load_rb_file.rb “: funziona sempre! qualunque sia la class di destinazione è una nuova class o una “class aperta” o “patch scimmia” per la class esistente, funziona sempre!

Per ulteriori dettagli, consultare: https://stackoverflow.com/a/6797707/445908

Molto simile, ma penso che questo sia un po ‘più elegante:

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

Nel mio caso stavo cercando di caricare semplicemente un file direttamente sotto la directory lib.

All’interno di application.rb …

 require '/lib/this_file.rb' 

non funzionava, anche in console e poi quando ho provato

 require './lib/this_file.rb' 

e le guide caricano perfettamente il file.

Sono ancora piuttosto noob e non sono sicuro del motivo per cui funziona, ma funziona. Se qualcuno volesse spiegarmelo, lo apprezzerei: DI spero che questo aiuti qualcuno in entrambi i modi.

Ho avuto lo stesso problema. Ecco come l’ho risolto. La soluzione carica la directory lib e tutte le sottodirectory (non solo quelle dirette). Ovviamente puoi usare questo per tutte le directory.

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

config.autoload_paths non funziona per me. Lo risolvo in altro modo

Ruby on rails 3 non carica automaticamente il codice (autoload) dalla cartella / lib. Lo risolvo inserendo ApplicationController

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

Se solo alcuni file hanno bisogno di accedere ai moduli in lib, basta aggiungere una dichiarazione require ai file che ne hanno bisogno. Ad esempio, se un modello deve accedere a un modulo, aggiungere:

 require 'mymodule' 

nella parte superiore del file model.rb.

Ci sono diversi motivi per cui potresti avere problemi a caricare da lib – vedi qui per i dettagli – http://www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classs-in-production/

  • correggere il percorso di caricamento automatico
  • correlato al thread
  • denominazione relativa

A partire da Rails 5 , si consiglia di mettere la cartella lib sotto la directory app o invece di creare altri spazi di nomi significativi per la cartella come services , presenters , features ecc. E metterli nella directory app per il caricamento automatico per rotaia.

Si prega di controllare anche questo link di discussione su GitHub .

Scrivi correttamente il nome del file.

Sul serio. Ho combattuto con una class per un’ora perché la class era Governance :: ArchitectureBoard e il file era in lib / governance / architecture_baord.rb (trasposto O e A in “board”)

Sembra ovvio in retrospettiva, ma è stato il diavolo a rintracciarlo. Se la class non è definita nel file che Rails si aspetta che sia in base al munging del nome della class, semplicemente non la troverà.