Ruby on Rails 3 - Ricarica la directory lib per ogni richiesta
-
17-09-2020 - |
Domanda
Sto creando un nuovo motore per un'applicazione Rails 3.Come puoi immaginare, questo motore si trova nella directory lib della mia applicazione.
Tuttavia, ho alcuni problemi nello svilupparlo.In effetti, devo riavviare il mio server ogni volta che cambio qualcosa nel motore.
C'è un modo per evitarlo ?
Posso forzare i rail a ricaricare completamente la directory lib o un file specifico e i suoi requisiti per ogni richiesta?
Grazie per l'aiuto :)
Soluzione
TL;DR
inserisci questo config/applicazione.rb
config.eager_load_paths += ["#{Rails.root}/lib"]
rimuovere
require
dichiarazioni per il tuo lib File
Andare!
Lasciami spiegare in dettaglio.
Non so perché questa risposta sia accettata, dal momento che non aiuta ricaricando la cartella lib su ogni richiesta.Innanzitutto pensavo che funzionasse per Rails 2, ma la domanda afferma chiaramente che era per Rails 3 e la data di rilascio di 3.0.0 è precedente alla data della risposta.
Altre risposte sembrano eccessivamente complicate o non forniscono una soluzione reale.
Ho deciso di indagare un po' sulla cosa, perché mi dava fastidio e ho anche scoperto che alcune persone hanno una soluzione alternativa a questo problema e prevede il salvataggio dei file lib all'interno app/models
in fase di sviluppo e poi spostarlo in /lib
quando fatto.Possiamo fare di meglio, vero?
La mia soluzione è testata rispetto a:
- Rotaie 3.0.20
- Rotaie 3.1.12
- Rotaie 3.2.13
- Rotaie 4.0.0.rc1
Metti questo nel tuo config/application.rb
:
# in config/application.rb
config.eager_load_paths += ["#{Rails.root}/lib"]
Questo è tutto!™
Assicurati di inserirlo qui poiché lo farà non funziona se lo metti dentro config/environments/development.rb
, Per esempio.
Assicurati di rimuovere tutto il file require
dichiarazioni per il tuo /lib
codice da allora require
dichiarazioni faranno sì che questa soluzione non funzioni.
Questo codice richiede implicitamente il tuo codice, quindi se esegui controlli ambientali (che non sono necessari) e invece del codice sopra, decidi di scrivere qualcosa del genere:
# in config/application.rb
config.eager_load_paths += ["#{Rails.root}/lib"] if Rails.env.development?
dovresti stare attento al vecchio require
dichiarazioni, poiché sono ancora richieste in tutti gli ambienti non di sviluppo, in questo scenario.
Pertanto, se decidi comunque di eseguire controlli ambientali, assicurati di eseguire controlli inversi per le istruzioni require.Altrimenti verrai morso!
require "beer_creator" unless Rails.env.development?
Potresti pensare che scrivere un intero paragrafo su qualcosa che non è necessario sia altrettanto inutile, ma penso che sia necessario anche avvertire le persone su qualcosa che è necessario quando si fa qualcosa di non necessario.
Se desideri saperne di più su questo argomento, dai un'occhiata questo piccolo tutorial.
Altri suggerimenti
Non ho potuto ottenere nessuno dei precedenti per lavorare per me, quindi ho scavato il codice dei binari un po 'e ho trovato questo:
Nuovo file: config / inizializzatori / ricarica_lib.rb
if Rails.env == "development"
lib_reloader = ActiveSupport::FileUpdateChecker.new(Dir["lib/**/*"]) do
Rails.application.reload_routes! # or do something better here
end
# For Rails 5.1+
ActiveSupport::Reloader.to_prepare do
lib_reloader.execute_if_updated
end
# For Rails pre-5.1
ActionDispatch::Callbacks.to_prepare do
lib_reloader.execute_if_updated
end
end
.
Sì, so che è disgustoso, ma è un hack.Potrebbe esserci un modo migliore per innescare una ricarica completa, ma funziona per me.La mia custodia specifica dell'uso è stata una app rack montata su una rotta rotaia, quindi ne avevo bisogno per ricaricare come ho lavorato su di esso nello sviluppo.
Fondamentalmente ciò che fa è controllare se sono stati modificati file in / lib (timestamp modificati) dall'ultima volta caricata e quindi attiva una ricarica se cambiano.
Potrei anche dire che ho questo nella mia configurazione / application.rb
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
.
Quale solo per impostazione predefinita assicura che tutto nella mia directory lib viene caricato.
YAYS!
Dato che stiamo parlando dei binari, il modo più semplice è quello di "richiedere" i tuoi file lib / * .rb usando ' require_dependency '.Finché il controller / helper / etc (file .rb sotto APP /) utilizza Require_Depency invece di richiedere solo il ricaricamento dei lavori, senza la necessità di fare nulla di funky.
Prima di scadere quella pista, l'unica soluzione che ha funzionato è stata quella su hemju.com , ma non volevo davvero dover tacere l'applicazioneController per la velocità del dev.
Devi aggiungere
config.autoload_paths += %W(#{config.root}/lib)
.
alla classe dell'applicazione in Config / Application.rb
https://rails.LighthouseApp.com/projects/8994/Tickets/5218-Rails-3-RC-Dees-Not-AutoLoad-From-lib
In Rails 3, ecco la salsa segreta per ricaricare automaticamente i file lib file.Il codice qui sotto è un po 'eccessivo, per l'esempio, ma è quello che ho fatto per farlo funzionare.È possibile modificare il messaggio in yoyo # gogo e vederlo sullo schermo ogni carico della pagina.Rimuovere l'inizializzazione e rimane lo stesso.
/config/initializers/lib_reload.rb (nuovo file)
ActiveSupport::Dependencies.explicitly_unloadable_constants << 'YoYo'
ActiveSupport::Dependencies.autoload_once_paths.delete(File.expand_path(File.dirname(__FILE__))+'/lib')
.
/lib/yo_yo.rb
class YoYo
def gogo
"OH HAI THERE"
end
end
.
/ app / controller / home_controller
require 'yo_yo'
class HomeController < ApplicationController
def index
@message = YoYo.new.gogo
end
end
. Ecco la mia versione ispirata a @pbhogan 's Risposta che ricarica tutti i file Ruby nella tua directory Rails / Lib quando viene modificato uno qualsiasi di questi file.
Silenzia anche avvertenze per evitare messaggi relativi alle costanti già inizializzate.
Lavori a causa di rotaie 3.2.8
if Rails.env.development?
lib_ruby_files = Dir.glob(File.join("lib/**", "*.rb"))
lib_reloader ||= ActiveSupport::FileUpdateChecker.new(lib_ruby_files) do
lib_ruby_files.each do |lib_file|
silence_warnings { require_dependency(lib_file) }
end
end
ActionDispatch::Callbacks.to_prepare do
lib_reloader.execute_if_updated
end
end
. Risposta aggiornata
Riassumo tutte le mie scoperte sul mio blog, faresti meglio a guardare lì:
- http://lsd4coders.muheimwebdesign.ch/2012/09/how-to-develop-rails-3-1-engines-with-ease-part-i-the-engine/
- http://lsd4coders.muheimwebdesign.ch/2012/09/how-to-develop-rails-3-1-engines-with-ease-part-ii-the-gem/
Vecchia risposta
Ho cercato una soluzione anche per questo, e (per completezza e anche per indirizzare gli altri in questa direzione) ecco cosa ho trovato.
A partire da Rails3.1, i motori possono essere facilmente generati tramite il comando rails plugin new my_plugin --full
.Questo genera lo scheletro di un motore.
--full
significa che il motore verrà "unito" direttamente nell'applicazione inclusa, in modo che, ad esempio, i controller siano direttamente accessibili come se fossero definiti nell'app inclusa.Ciò ti consente ad es.avere un file di supporto dentro my_engine/app/helpers/my_helper.rb
che verrà unito direttamente alle tue app incluse app/helpers/my_helper.rb helper
.
C'è un'altra opzione --mountable
che crea uno spazio dei nomi per il motore in modo che i suoi controller, ecc.non entrerà mai in collisione con quelli dell'applicazione inclusa.Ciò si traduce ad es.è presente un aiutante my_engine/app/helpers/my_engine/my_helper.rb
che non si scontrerà con un aiutante app/helpers/my_helper.rb
nella tua app inclusa.
Ora la parte più interessante:
All'interno del motore generato test
cartella, c'è un file dummy
cartella che contiene un'applicazione Rails completa!Per cosa è?
Quando si sviluppa un motore, le sue funzionalità sono pensate per funzionare completamente in autonomia e dovrebbero anche essere testate completamente in autonomia.Quindi è il modo "sbagliato" di sviluppare un motore "all'interno" di un'altra app Rails (anche se questo intuitivamente spesso sembrerà corretto quando si estraggono funzionalità esistenti da un'app Rails in un motore), e quindi teoricamente non è nemmeno necessario ricaricare il motore di un motore. codice con ogni richiesta all'applicazione inclusa.
Il modo "giusto" sembra essere questo:sviluppa e testa il tuo motore, come se fosse un'app Rails completa utilizzando il dummy
applicazione!Qui puoi fare tutto ciò che puoi fare in qualsiasi app Rails "normale", ad es.creare controller, modelli, viste, ecc.che utilizzano le funzionalità che il motore dovrebbe fornire.Normalmente puoi anche avviare un server utilizzando rails s
nel tuo test/dummy
directory e accedi all'app fittizia su localhost:3000
, e durante l'esecuzione dei test, il file dummy
l'app viene utilizzata automaticamente per i test di integrazione.Piuttosto bella!:-)
Devi stare attento a dove mettere le tue cose:
- Qualsiasi funzionalità destinata a essere utilizzata all'interno di un'altra app Rails entra in
my_engine/app
, mentre vengono inserite tutte le funzionalità necessarie solo per testare la funzionalità del motoretest/dummy/app
.
Successivamente potrai caricare facilmente il tuo motore nell'app principale Gemfile
come questo: gem 'my_engine', :path => 'path/to/my_engine'
o pubblicalo su GitHub come gioiello.
(Una cosa interessante (e per tornare all'argomento di questo argomento) è che quando avvio il server del manichino, tutti i cambiamenti nel motore sembrano riflettersi al suo interno!Quindi in qualche modo sembra possibile includere un motore all'interno di un'app Rails senza memorizzarlo nella cache...?Non so come ciò avvenga.)
Quindi riassumendo:un motore fornisce funzionalità che possono reggersi completamente da sole, quindi dovrebbe anche essere sviluppato e testato da solo.Quindi, quando avrà raggiunto uno stato stabile, potrà essere incluso da qualsiasi altra app che necessiti delle sue funzionalità.
Ecco alcune risorse che trovo utili:
Spero che troverai utile questa risposta.Sono ancora molto nuovo ai motori in generale, quindi se ci sono informazioni errate, per favore dimmelo e io le correggerò.
Aggiungi a application_controller.rb
o il tuo controller di base:
before_filter :dev_reload if Rails.env.eql? 'development'
def dev_reload
# add lib files here
["rest_client.rb"].each do |lib_file|
ActiveSupport::Dependencies.load_file lib_file
end
end
.
ha funzionato per me.
Nota che in Rails 3 "Load_once_paths" diventa "autoload_once_paths."
Inoltre, sembra che dovrebbe essere vuoto a meno che non metti esplicitamente qualcosa in esso.
Inoltre, assicurati di commentare la seguente riga in Application.rb (oltre alla soluzione di @ Dishod) e assicurati che il nome del modulo sia lo stesso del tuo nome del file (altrimenti, i binari non saranno in gradoper trovarlo)
#Dir.glob("./lib/*.{rb}").each { |file| require file } # require each file from lib directory
. Worked for Rails 3.2.13 for reloading lib inside of gem of an app:
require_dependency 'the_class'
AND
config.autoload_paths += %W(#{config.root}/../fantasy/lib)