我有一个带有lib
API的Ruby on Rails应用程序。 lib
中的文件是自动加载的,API是在初始化程序中配置的。
# 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
这适用于生产,但在开发过程中,API会在服务器启动时进行配置。更改某些代码后,配置会丢失,并且由于设置为nil
而导致错误:
irb(main):001:0> MyApi.my_setting
=> "foo"
irb(main):002:0> reload!
Reloading...
=> true
irb(main):003:0> MyApi.my_setting
=> nil
我的猜测是,在开发过程中,会重新加载类,但初始化程序不会,这意味着它只能在启动服务器后配置一次。
现在我正在lib/my_api.rb
复制我的配置,但这非常hacky。
这个问题的解决方案是什么?
答案 0 :(得分:0)
module MyApi
module Configuration
mattr_accessor :my_setting
def configure
yield self
end
end
end
mattr_accessor
是一个用于创建模块级访问器的ActiveSupport宏。
答案 1 :(得分:0)
好吧,在有人提出更好的解决方案之前,我已经提出了两个解决方法。我跟2去了。
lib
目录(意味着不自动加载API)。这意味着必须在API代码更改时重新启动服务器,但解决了问题。这就是配置这样的宝石的原因 - 因为它们不是自动加载的。在lib/my_api.rb
:
load Rails.root.join('config/initializers/smart_meter.rb') if Rails.env.development?
当Rails自动加载类时,MyApi
常量将被新的常量替换。配置仍可在旧对象上使用:
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"