Moduły Rails / lib oraz

Piszę Niestandardowy wrapper dla open_flash_chart plugin. Jest umieszczony w /lib i załadowany jako moduł w ApplicationController.

Jednak mam pewien problem z hierarchią klas lub smth.

Z dowolnego kontrolera mogę uzyskać dostęp do funkcji open_flash_chart jako OpenFlashChart, Line etc

Jednak w klasie w module /lib to nie działa!

Jakieś pomysły?
Author: Jonathan Bender, 2009-07-02

5 answers

Są dwa sposoby ładowania plików w Rails:

  • jest rejestrowany w procesie autoload i odwołujesz się do stałej odpowiadającej nazwie pliku. Na przykład, jeśli masz app/controllers/pages_controller.rb i reference 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 i nie jest częścią normalnego procesu ładowania Ruby.
  • pliki są jawnie required. Jeśli plik jest required, Ruby wygląda przejrzyj całą listę ścieżek w ścieżkach ładowania i znajdź pierwszy przypadek, w którym plik required znajduje się w ś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, więc Rails automatycznie je odbierze, gdy odwołasz się do danej stałej, albo wyraźnie wymaga modułu.

Zauważam również, że możesz być zmieszany z inną sprawą. ApplicationController jest Nie głównym obiektem w systemie. Obserwuj:

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żyć.

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 mieć go dostępnego (przy użyciu jednej z powyższych technik).

 145
Author: Yehuda Katz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-02 17:11:41

W Rails 3 / lib Moduły nie są ładowane automatycznie.

To dlatego, że linia:

# config.autoload_paths += %W(#{config.root}/extras)

Wewnątrz config / aplikacji.rb jest komentowany.

Możesz spróbować odkomentować ten wiersz lub, (dla mnie to działało jeszcze lepiej), zostawić ten komentarz (dla przyszłych odniesień) i dodać te dwie linijki:

config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
 81
Author: diegopau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-20 11:01:07

To, co u mnie zadziałało, poza tym, że Config nie działa.autoload_paths (I ' m on Rails 3.1.3), było stworzenie inicjalizatora takiego jak:

#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 klas Model.mymodule_method lub jako metody instancji mymodel.mymodule_method

Może jakiś ekspert może wyjaśnić konsekwencje tego. Do tej pory używaj go na własne ryzyko.

Edit: potem myślę, że lepszym rozwiązaniem byłoby:

Utwórz inicjalizator jak to:

#config/initializers/myapp_init.rb
require ‘my_module’

Dołącz moduł w razie potrzeby, w następujący sposób:

1) jeśli chcesz użyć go jako "metody klasy" użyj "extend":

class Myclass < ActiveRecord::Base
   extend MyModule
   def self.method1
      Myclass.my_module_method
   end
end

2) jeśli chcesz użyć go jako "metody instancji", dodaj go do 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 pliku my_module.rb w ścieżce ładowania, który musi być najpierw wymagany

 20
Author: Fernando Fabreti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-19 09:11:32

Aby używać modułu lib/my_module.rb w 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

Metoda ta jest opisana bardziej szczegółowo w http://hakunin.com/rails3-load-paths

 2
Author: Dennis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-12 16:27:08

Może się zdarzyć, że podczas inicjalizacji aplikacji będziesz chciał jawnie załadować pliki w katalogu lib.
w moim config / aplikacji.rb, mam wpis jako,
config.autoload_paths += %W(#{config.root}/lib)

może się również zdarzyć, że nazwa / hierarchia modułu nie jest taka sama jak w pliku lub lokalizacja / nazwa pliku nie jest taka sama jak w tej hierarchii, 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
zadziałało dobrze.

 0
Author: Swapnil Chincholkar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-12 08:11:16