2015-07-20 9 views
6

Ich habe eine Ruby on Rails App mit einer API in lib. Dateien in lib werden automatisch geladen, und die API wird in einem Initialisierer konfiguriert.Ruby on Rails: Konfigurieren der API in Initialisierung in Entwicklung

# lib/my_api.rb 
module MyApi 
    extend Configuration 
end 

# lib/my_api/configuration.rb 
module MyApi 
    module Configuration 
    attr_accessor :my_setting 
    def configure 
     yield self 
    end 
    end 
end 

# config/initializers/my_api.rb 
MyApi.configure do |config| 
    config.my_setting = 'foo' 
end 

Dies funktioniert in der Produktion, sondern in der Entwicklung der API konfiguriert wird, wenn der Server gestartet wird. Nachdem ich einige Code ändern, wird die Konfiguration verloren und es gibt Fehler, da die Einstellungen sind nil:

irb(main):001:0> MyApi.my_setting 
=> "foo" 
irb(main):002:0> reload! 
Reloading... 
=> true 
irb(main):003:0> MyApi.my_setting 
=> nil 

Meine Vermutung ist, dass in der Entwicklung werden die Klassen neu geladen, aber die initializer ist nicht, was bedeutet, nur wird es Einmal nach dem Start des Servers konfiguriert.

Im Moment dupliziere ich meine Konfiguration in lib/my_api.rb, aber das ist sehr hacky.

Was ist eine saubere Lösung für dieses Problem?

Antwort

0

Nun, bis jemand eine bessere Lösung gefunden hat, habe ich zwei Problemumgehungen. Ich ging mit 2.

  1. Das Verzeichnis lib nicht autoload (dh nicht die API automatisch laden). Das bedeutet, dass Sie den Server neu starten müssen, wenn sich der API-Code ändert, aber das Problem löst. Deshalb funktioniert das Konfigurieren von Edelsteinen wie diese - weil sie nicht automatisch geladen werden.
  2. manuell nachladen die Initialisierung in der Entwicklung am Ende des lib/my_api.rb:

    load Rails.root.join('config/initializers/smart_meter.rb') if Rails.env.development?

Die MyApi Konstante wird durch eine neue, wenn Rails autoloads Klassen ersetzt werden. Die Konfiguration ist weiterhin für das alte Objekt verfügbar:

Loading development environment (Rails 4.2.0) 
irb: warn: can't alias context from irb_context. 
irb(main):001:0> MyApi.my_setting 
=> "foo" 
irb(main):002:0> OldMyApi = MyApi 
=> MyApi 
irb(main):003:0> reload! 
Reloading... 
=> true 
irb(main):004:0> MyApi.my_setting 
=> nil 
irb(main):005:0> OldMyApi.my_setting 
=> "foo" 
irb(main):006:0> load Rails.root.join('config/initializers/smart_meter.rb') 
=> true 
irb(main):007:0> MyApi.my_setting 
=> "foo" 
0

mattr_accessor ist ein ActiveSupport-Makro zum Erstellen von Zugriffsmodulen auf Modulebene.

+1

Gemäß der Dokumentation, 'mattr_accessor'" Definiert sowohl Klassen- als auch Instanz-Accessoren für Klassenattribute. " Es ändert nichts an Autoloading, was leider bedeutet, dass es mein Problem nicht löst. – amiuhle

+0

Wenn Sie das Attribut für die Klasse definieren, müssen Sie den initailizer nur einmal ausführen. Wenn rails die Klasse erneut lädt, wird die Variable weiterhin gespeichert. – max

+0

Ich habe es versucht, es macht keinen Unterschied. Ich schätze, die Klasse wird neu geladen, was bedeutet, dass es sich um eine andere Klasseninstanz im Speicher handelt. Die Konfiguration bezieht sich auf die alte Klasseninstanz, nicht auf die neue. In der rails-Konsole ruft 'MyApi.my_setting' korrekt' foo' zurück, nach 'reload!' 'MyApi.my_setting gibt' nil' zurück – amiuhle