这个Rails引擎代码意味着什么:config.to_prepare&method(:activate).to_proc

Jac*_*lla 10 spree ruby-on-rails-3

我正在使用Spree,它广泛使用Rails引擎.我发现的常见模式是这个.但是我无法理解这段代码.

class Engine < Rails::Engine 
  def self.activate
    ...
  end     

  config.to_prepare &method(:activate).to_proc
end
Run Code Online (Sandbox Code Playgroud)
  1. 做了.to_prepare什么
  2. 什么是&method运营商吗?
  3. 代码的整体效果如何?

非常感谢!

Mic*_*ley 39

&method(:activate).to_proc

这最好一次消耗一个项目.(应该注意的是,这部分代码是100%特定于Rails的Ruby.)

method是一个Ruby方法(它都是非常元).因此记录在案:

在obj中查找命名方法作为接收者,返回一个Method对象(或引发NameError).Method对象充当obj对象实例中的闭包,因此实例变量和self的值仍然可用.

查看以下IRB会话:

ruby-1.9.2-p136 :001 > def my_method
ruby-1.9.2-p136 :002?>   puts "in my_method"
ruby-1.9.2-p136 :003?>   10
ruby-1.9.2-p136 :004?>   end
 => nil 
ruby-1.9.2-p136 :005 > method(:my_method)
 => #<Method: Object#my_method>
Run Code Online (Sandbox Code Playgroud)

因此method调用正在查找(在您的示例中)activate方法并为其创建Method对象.Method包含一个名为的方法to_proc,它" 返回与此方法对应的Proc对象 ".继续我们的IRB会议:

ruby-1.9.2-p136 :006 > method(:my_method).to_proc
 => #<Proc:0x000001010a3e38 (lambda)>
Run Code Online (Sandbox Code Playgroud)

最后,我们使用&符号运算符,当Proc在方法调用期间在对象之前时,它将被Proc包含的块替换.在IRB再一次:

ruby-1.9.2-p136 :007 > def executor(&block)
ruby-1.9.2-p136 :008?>   block.call
ruby-1.9.2-p136 :009?>   end
 => nil 
ruby-1.9.2-p136 :010 > executor( &method(:my_method).to_proc )
in my_method
 => 10
Run Code Online (Sandbox Code Playgroud)

所以,在伪代码中,你列出的那句话是:

config.to_prepare(a block containing the functionality of the method activate)
Run Code Online (Sandbox Code Playgroud)

config.to_prepare

[根据schof的评论编辑]

config.to_prepare需要运行一个块来设置你的Railtie/Engine.它在生产模式和开发中的每个请求中运行一次,并且是唯一保证在开​​发模式下的每个请求上调用的代码.如果要class_eval在引擎初始化过程中修改类(等),这很重要; 否则,你会看到开发与生产中的不同行为.

但为什么?

这是一个常见习语的原因是你不必在to_prepare块本身内定义你的准备代码; 您可以在类中定义方法,然后使用上述魔法将它们转换为块(记住其范围).代码在功能上等同于:

class Engine < Rails::Engine 
  config.to_prepare do
    (the contents of self.activate)
  end
end
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案.只是想补充一点,config.to_prepare东西是唯一保证在开发模式下每个请求都被调用的东西.如果要将类(class_eval等)修改为引擎init的一部分,这一点很重要.否则你会在开发与生产中看到不同的行为. (3认同)