Rails.application.configure块如何在不提供变量名

时间:2018-01-22 10:21:40

标签: ruby-on-rails ruby

在Rails中,看到这样的模式很常见(例如在config/environments/development.rb中):

Rails.application.configure do

  config.some_option = some_value

end

由于我最近正在研究如何配置blocks工作并最终发现this very similar patternconfigure方法初始化(通常记忆)的一个实例,因此我被这个成语所吸引。配置类(具有配置选项的访问器)并将该实例对象生成块。像这样:

module Clearance
  class << self
    attr_accessor :configuration
  end

  def self.configure
    self.configuration ||= Configuration.new
    yield(configuration)
  end

  class Configuration
    attr_accessor :mailer_sender

    def initialize
      @mailer_sender = 'donotreply@example.com'
    end
  end
end

这就是Clearance.configure {|config| config.mailer_sender = 'something'}工作的原因,因为它将配置类的实例产生为块变量config

但是Rails的做法是,没有变量被传递给那个块。没有Rails.application.configure do |config|,因此该块可以更改配置对象访问器。我认为config在该区块内未定义,但它不是。

尝试查看rails源代码,我怀疑它与configurable module有关,但我无法100%理解我在那里找到的代码。

2 个答案:

答案 0 :(得分:1)

实际的Rails铁路似乎没有使用Configurable模块。

https://github.com/rails/rails/blob/5ccdd0bb6d1262a670645ddf3a9e334be4545dac/railties/lib/rails/railtie.rb#L170

我没有声称完全了解它的用法,但显然是delegate方法used in Railtie class

delegate :config, to: :instance

添加config属性,指向Rails::Application::Configuration的实例 - 我们稍后通过Rails.application.config访问的实例。

https://apidock.com/rails/Module/delegate

答案 1 :(得分:0)

它使用instance_eval(或基本相同的class_eval)来评估指定对象上下文中的块。在该块内,该对象成为隐式接收器(即self)。

例如,使用您的代码:

module Clearance
  class << self
    attr_accessor :configuration
  end

  def self.configure(&block)
    self.configuration ||= Configuration.new
    configuration.instance_eval(&block)
  end

  class Configuration
    attr_accessor :mailer_sender

    def initialize
      @mailer_sender = 'donotreply@example.com'
    end
  end
end

Clearance.configure { self.mailer_sender = 'something' }

Clearance.configuration.mailer_sender #=> "something"