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 :)

È stato utile?

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ì:

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 motore test/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)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top