2012-03-21 3 views
15

Quando si memorizzano i file in una directory personalizzata (ad es .: app/presenters/), come si assicura che le classi con spazi dei nomi vengano caricate?Prevenzione di "avviso: costante di livello B referenziata da A :: B" con classi con nomi assegnati in Rails

Ad esempio, se si dispone di:

Rails non riesce a caricare MegaMenu::CatalogPresenter:

CatalogPresenter.new 
=> #<CatalogPresenter:0x85bca68 @_routes=nil> 

MegaMenu::CatalogPresenter.new 
(irb):3: warning: toplevel constant CatalogPresenter referenced by MegaMenu::CatalogPresenter 
=> #<CatalogPresenter:0x85750a0 @_routes=nil> 

Ho creato un sample Rails 3.2 app that reproduces this problem.

In config/application.rb, app's configured to load files in app/presenters/.

risposta

17

Ho risolto questo problema utilizzando una dichiarazione richiedono in un inizializzatore. Non mi piace molto ma mi sono piaciuti i nomi di struttura e classe della mia applicazione, avevano senso quindi un inizializzatore era la soluzione migliore. Nella inizializzatore prova:

require File.join(Rails.root, "app", "presenters", "mega_menu", "catalog_presenter") 
require File.join(Rails.root, "app", "presenters", "catalog_presenter") 

Questo problema si verifica perché caricamento automatico si basa su const_missing essere chiamato che non accadrà nel tuo caso.

Quando il rubino incontra per la prima volta un riferimento a MegaMenu :: CatalogPresenter, il file mega_menu/catalog_presenter.rb non è stato incluso. Il comportamento standard del ruby ​​lo fa risalire all'albero dei nomi (figura retorica) e trova invece il riferimento di livello superiore CatalogPresenter come questo è stato incluso a questo punto.

+0

Si applica allo stesso modo alla directory app/modelli? Ho un'app/models/people/data.rb e ottengo la stessa eccezione perché Data è già definita. – joshhepworth

+2

Questo si applica ovunque. È solo questione di come vengono risolte le costanti mancanti. Se si assicura di richiedere esplicitamente entrambi i modelli, non si dovrebbe incorrere in questo problema. –

0

La creazione di nuove costanti toplevel all'interno delle classi solleva questo errore. Volete qualcosa di più simile in catalog_presenter.rb:

class MegaMenu 
    class MegaMenu::CatalogPresenter 
    end 
end 
+0

Grazie per il suggerimento, Veraticus. Sfortunatamente, dopo aver apportato questa modifica, il problema esiste ancora. Sembra che Rails non sappia che dovrebbe cercare 'app/presenters/mega_menu/catalog_presenter.rb'. – nickh

+0

Oh bene, ne valeva la pena. :/L'unico altro suggerimento che farei è di aggiungere '' 'app/presenters/mega_menu''' manualmente ai percorsi di autoload e vedere se lo corregge. – Veraticus