2009-09-21 7 views
54

In che modo differiscono require e require_dependency?
Come può require_dependency ricaricare automaticamente le classi in fase di sviluppo ma non è possibile eseguire require?In che modo sono necessari il relaading require, require_dependency e costanti in Rails?

Ho inserito nel codice ActiveSupport::Dependencies di Rails e nel codice dispatcher.rb. Quello che ho visto nel codice require_dependency è fondamentalmente aggiunge le costanti ad una matrice autoloaded_constants. Ma viene cancellato in clear_application all'interno del dispatcher dopo ogni richiesta.

Qualcuno può dare una spiegazione chiara o indicarmi alcune risorse che aiuteranno?

+0

FYI: La ricarica classe è gestito automaticamente nei motori (che non sono altro che i plugin con app/cartelle), proprio come se fossero in normali applicazioni. –

+0

Grazie, Sì, ne sono consapevole. Ma questo porta alla mia altra domanda: Posso usare altri plugin nel mio plugin? Supponiamo che io voglia utilizzare un plug-in act_as_xxx nel mio plugin, posso semplicemente inserire act_as_xxx nella directory del fornitore/plug-in del mio plug-in e quindi aggiungere il percorso a $ LOAD_PATH? Credo che dovrei chiedere questo in un altro thread che non è correlato alla mia domanda originale. – wei

risposta

108

require (e suo cugino load) sono metodi core di Ruby. require_dependency è un metodo che consente a Rails di gestire il problema della gestione delle dipendenze. Per farla breve, consente a Rails di ricaricare le classi in modalità di sviluppo in modo da non dover riavviare il server ogni volta che si effettua un cambio di codice. Il framework Rails sostituirà il codice require_dependency in modo che possa monitorarlo e ricaricarlo quando vengono apportate modifiche. Lo standard Ruby require non lo fa. Come sviluppatore di app (o plugin/engine) non dovresti preoccuparti di require_dependency dato che è puramente interno a Rails.

La magia del processo di caricamento della classe Rails è nel modulo ActiveSupport :: Dependencies. Questo codice estende il comportamento predefinito di Ruby per consentire al codice all'interno dell'app Rails di caricare automaticamente i moduli (incluse le classi che ereditano dal modulo) utilizzando le convenzioni di denominazione dei percorsi e dei file di Rails. Ciò elimina la necessità per il programmatore di sparpagliare il proprio codice con le chiamate require come in una semplice applicazione Ruby.

per dirla in altro modo, questo permette di definire class Admin::User all'interno del file app/models/admin/user.rb e hanno Rails sanno che cosa si sta parlando quando si chiama Admin::User.new da un'altra parte della domanda come un controller. Senza ActiveSupport :: Dipendenze coinvolte si dovrebbe manualmente require tutto il necessario.

Se si proviene da un linguaggio tipizzato in modo statico come C#, Java, ecc, potrebbe essere una sorpresa: il codice Rails non viene caricato finché non è necessario. Ad esempio, una classe di modello User non è definita e lo user.rb non viene caricato fino a quando NON si prova a chiamare User.whatever_method_here. Rails impedisce a Ruby di lamentarsi della costante mancante, carica il codice per User e quindi consente a Ruby di continuare normalmente.

Anche se non riesco a parlare per le vostre specifiche esigenze, sarei molto sorpreso se fosse effettivamente necessario utilizzare il metodo require_dependency da un plug-in o un motore. Se segui le convenzioni Rails, non dovresti modificare a mano $ LOAD_PATH. Questo non è "il modo Rails".

Nel mondo di Ruby e anche Rails la semplicità e la chiarezza è la chiave. Se tutto ciò che vuoi è scrivere un plugin o un motore e ti stai già immergendo in profondità all'interno, allora potresti considerare di affrontare il tuo problema da una prospettiva diversa. Il mio istinto mi dice che potresti provare a fare qualcosa che è inutilmente complicato. Ma poi di nuovo, non ho idea di quello che stai facendo esattamente !! :)

16

require_dependency è utile in un motore quando si desidera riaprire una classe non definita nel motore (ad esempio in un altro motore o in un'app Rails) e ricaricarla.In tal caso, qualcosa di simile a questo funziona:

# app/controllers/my_engine/documents_controller.rb 
require_dependency MyEngine::Engine.root.join('app', 'controllers', 'my_engine', 'documents_controller').to_s 

module MyEngine 
    class DocumentsController 
    def show 
     render :text => 'different' 
    end 
    end 
end