2009-10-07 13 views
11

Rozszerzam klasy (która jest w plugin) poprzez włączenie modułu, odbywa się to w inicjator.Jak przedłużyć klasę z inicjalizatora i załadować ją ponownie w środowisku programistycznym?

require 'qwerty/core/user' 
User.send :include, Qwerty::Core::Extensions::User 

Jednak w rozwoju przed każdą prośbę (i po przeładowaniu! Nazywany jest w konsoli) Wszystkie modele są przeładowane, ale dlatego, że nie są prowadzone inicjalizatory ponownie moduł nie jest wliczony w cenę. Pozostawienie modelu z "brakującymi częściami".

Ponieważ model jest w wtyczce, nie wydaje się rozsądne dołączanie kodu bezpośrednio do klasy, co byłoby typowym podejściem.

Na razie dodałem po prostu filtr before_filter, który zawiera moduł, jeśli znajduje się w środowisku programistycznym. Ale mam skopiować/wkleić i mieć duplikat kodu w inicjatora i kontrolera aplikacji.

# Class extensions in initalizers are over-writtern each request 
    def development_loading 
    if RAILS_ENV == 'development'  
     User.send :include, Qwerty::Core::Extensions::User 
    end 
    end 

Czy istnieje lepszy sposób?

marginesie plugin jest moja, więc mogę dodać kod do niego, ale rozszerzenia utrzymywane w module nie zawsze może być obecny ...

Odpowiedz

11

environment.rb

config.to_prepare do 
    User.send :include, Qwerty::Core::Extensions::User 
end 

Kod jest blok uruchamiany przed każdym żądaniem w trybie programowania i raz w trybie produkcyjnym.

+1

To działało dla mnie, ale w application.rb (rails 3.0.20), nie environment.rb – tekniklr

+0

To działa idealnie w szynach 4, jeśli dodasz to do engine.rb w silniku szyn. Dzięki! –

0

Dlaczego używacie inicjatorów obejmuje funkcjonalność?

Wypróbuj następujące zamiast:

require 'qwerty/core/user' 
class User < ActiveRecord::Base 
    include Qwerty::Core::Extensions::User 
    # bla bla 
end 
+0

Ponieważ on chce tylko ten kod włączony w trybie rozwoju. – SFEley

+0

Ponieważ model jest w wtyczce, która jest wtyczką, którą rozwijam, traktuję ją jak wtyczkę innej firmy, więc nie chcę dotykać kodu w niej. Muszę więc rozszerzyć te klasy z zewnątrz. – Kris

1

Początkowo miałem zamiar doradzić coś o dodanie katalogu „rozwój” do przodu ścieżki obciążenia w trybie rozwoju, tak aby zmiany zawsze się reloaded najpierw ... Ale potem przyszło mi do głowy, że powiedziałeś coś mylącego.

Model, który próbujesz rozszerzyć. Jest w wtyczce ? Wtyczki nie są domyślnie domyślnie ładowane ponownie w trybie programowania, chyba że aplikacja wyraźnie mówi, że powinny w swojej konfiguracji, ustawiając wartość Config.reload_plugins? na wartość false.

Ale jeśli z jakiegoś powodu Twój Wtyczka jest przeładunku i tak ty nie chcesz go można umieścić to w swoim pluginu init.rb wyraźnie powiedzieć, że nie należy przeładować:

Dependencies.load_once_paths << lib_path 

Zobacz docs szyn na klasy Configuration więcej szczegółów: http://api.rubyonrails.org/classes/Rails/Configuration.html#M002536

+0

Tak, mam reload_plugins? ustawione na true, ponieważ aktywnie rozwijam wtyczkę. Chcę opracować sposób rozszerzenia modeli w wtyczce z aplikacji Rails (tj. Bez dotykania kodu wtyczki). Trochę mylące tak! W moim init.rb mam: if RAILS_ENV == 'development' ActiveSupport :: Dependencies.load_once_paths.reject! {| X | x = ~ /^#{Regexp.escape(File.dirname(__FILE__))}/} koniec – Kris

+0

Myślę, że mój problem polega na tym, że próbuję wykonać dwie rzeczy naraz - pracę nad wtyczką (przeładuj to każde żądanie) i rozszerzyć wtyczkę z aplikacji Rails. Nieco złapać 22 ... – Kris

+0

Dlaczego? Po co dawać sobie te wszystkie ograniczenia? Nie chcesz dodawać kodu rozwojowego do wtyczki, nie chcesz ładować go tylko raz i chcesz cofnąć _idea_ wtyczki przez rozszerzenie wtyczki z twojej aplikacji (która jest filozoficznie wsteczna). Co zyskujesz ze wszystkich tych szczególnych przypadków? Czy dodajesz jakieś warunki "if RAILS_ENV == 'development'' do twojej wtyczki, która coś złamie? Zawsze możesz go później wyjąć lub umieścić rozszerzenia w plikach, które są dostępne tylko w specjalnym oddziale Git. Przestań walczyć z rzeką. Idź z prądem. Niech Rails be Rails. Zrób to. – SFEley

3

Nieco bardziej eleganckie rozwiązanie niż ten zaakceptowany, ponieważ może on być dopuszczony do inicjowania:

require 'dispatcher' 

Dispatcher.to_prepare do 
    # stuff that needs to happen once per initialization 
end 
6

w Rails 3.x można skonfigurować blok uruchomić za każdym razem ładuje się zdarzyć (w trybie rozwoju, lub gdy config.cache_classes = false).To byłoby w inicjalizatorze:

ActionDispatch::Callbacks.to_prepare do 
    # configure stuff or initialize 
end 
Powiązane problemy