Piszę niestandardowy wrapper dla open_flash_chart
wtyczki. Jest umieszczany /lib
i ładowany jako moduł ApplicationController
.
Jednak mam jakiś problem z hierarchią klas lub czymś.
Z dowolnego sterownika mogę uzyskać dostęp do open_flash_chart
funkcji jak OpenFlashChart
, Line
etc
Jednak w klasie w /lib
module to nie działa!
Jakieś pomysły?
ruby-on-rails
ruby
class
module
Mantas
źródło
źródło
Odpowiedzi:
Pliki są ładowane do Railsów na dwa sposoby:
app/controllers/pages_controller.rb
i odwołujesz się do PagesController,app/controllers/pages_controller.rb
zostanie automatycznie załadowany. Dzieje się tak w przypadku wstępnie ustawionej listy katalogów w ścieżce ładowania. Jest to cecha Railsów i nie jest częścią normalnego procesu ładowania Rubiego.require
d. Jeśli plik jestrequire
d, Ruby przegląda całą listę ścieżek w twoich ścieżkach ładowania i znajduje pierwszy przypadek, w którym plik, któryrequire
d, znajduje się na ścieżce ładowania. Możesz zobaczyć całą ścieżkę ładowania, sprawdzając $ LOAD_PATH (alias dla $ :).Ponieważ
lib
znajduje się w twojej ścieżce ładowania, masz dwie opcje: albo nazwij swoje pliki tymi samymi nazwami, co stałe, aby Railsy automatycznie je pobierały, gdy odwołasz się do danej stałej, lub wyraźnie zażądają modułu.Zauważyłem również, że możesz być zdezorientowany co do innej rzeczy. ApplicationController nie jest głównym obiektem w systemie. Przestrzegać:
module MyModule def im_awesome puts "#{self} is so awesome" end end class ApplicationController < ActionController::Base include MyModule end class AnotherClass end AnotherClass.new.im_awesome # NoMethodError: undefined method `im_awesome' for #<AnotherClass:0x101208ad0>
Będziesz musiał dołączyć moduł do dowolnej klasy, w której chcesz go używać.
class AnotherClass include MyModule end AnotherClass.new.im_awesome # AnotherClass is so awesome
Oczywiście, aby móc dołączyć moduł w pierwszej kolejności, musisz go mieć (używając jednej z powyższych technik).
źródło
W Railsach 3 / lib moduły nie są ładowane automatycznie.
Dzieje się tak, ponieważ linia:
# config.autoload_paths += %W(#{config.root}/extras)
wewnątrz config / application.rb jest komentowane.
Możesz spróbować odkomentować tę linię lub (dla mnie zadziałało to nawet lepiej), zostawić to skomentowane (do przyszłego wykorzystania) i dodać te dwie linie:
config.autoload_paths += %W(#{config.root}/lib) config.autoload_paths += Dir["#{config.root}/lib/**/"]
źródło
../lib
ścieżki wApplicationName::Application.config.autoload_paths
tablicy.config.autoload_paths += Dir["#{config.root}/lib/**/"]
powinno wystarczyć. @ckarbass Druga linia daje swobodę organizowania narzędzi w podfoldery, a tym samym ujednolicenia modułów za pomocą przestrzeni nazw . To prawie wszystko. A oto dlaczego wartość domyślna została zmieniona. Lepiej późno niż wcale :)Pomijając odkomentowanie config.autoload_paths (jestem na Railsach 3.1.3), zadziałało dla mnie stworzenie takiego inicjalizatora:
#config/initializers/myapp_init.rb require 'my_module' include MyModule
W ten sposób mogę wywoływać metody mymodule z dowolnego miejsca i jako metody klasowe
Model.mymodule_method
lub jako metody instancjimymodel.mymodule_method
Może jakiś ekspert wyjaśni konsekwencje tego. Teraz używaj go na własne ryzyko.
Edycja: Myślę, że później lepszym rozwiązaniem byłoby:
utwórz inicjalizator w następujący sposób:
#config/initializers/myapp_init.rb require ‘my_module’
W razie potrzeby dołącz moduł, na przykład:
1) jeśli chcesz używać go jako „Metody klasowe”, użyj opcji „rozszerz”:
class Myclass < ActiveRecord::Base extend MyModule def self.method1 Myclass.my_module_method end end
2) jeśli chcesz używać go jako „Metody instancji”, umieść go w definicji klasy:
class Myclass < ActiveRecord::Base include MyModule def method1 self.my_module_method end end
3) pamiętaj, że
include MyModule
odnosi się do plikumy_module.rb
w ścieżce ładowania, który musi być wymagany jako pierwszyźródło
lib
folderze, więc dodałemconfig.autoload_paths += %W(#{config.root}/lib)
naconfig/application.rb
pliku. Następnie postąpiłem zgodnie z twoją sugestią, aby dodaćconfig/initializers/myapp_init.rb
plik i jego zawartość. Wszystko jest dobrze.require
działa dla mnie, a automatyczne ładowanie nie działa (niezdefiniowana metoda modułu), ten komentarz mówi, że nie powinieneś używaćrequire
.Aby użyć modułu
lib/my_module.rb
w swoich modelach i kontrolerach:W
config/application.rb
:config.watchable_dirs['lib'] = [:rb]
W Twoim modelu (podobny pomysł na kontroler):
require_dependency 'my_module' class MyModel < ActiveRecord::Base include MyModule MyModule.some_method end
Ta metoda jest opisana bardziej szczegółowo pod adresem http://hakunin.com/rails3-load-paths
źródło
Może się zdarzyć, że chcesz jawnie załadować plik (i) do katalogu lib w czasie inicjalizacji aplikacji.
W moim config / application.rb mam wpis jako,
config.autoload_paths += %W(#{config.root}/lib)
Może się tak zdarzyć, że nazwa / hierarchia modułu nie jest taka sama, jak w pliku lub lokalizacja / nazwa pliku nie jest taka sama jak ta hierarchia, więc automatyczne ładowanie tego pliku również nie jest możliwe. Więc kiedy dodałem wpis na dole config / application.rb as,
require "./lib/file_name_without_extention
działał dobrze.
źródło