此代码中的&
(前缀为ActiveAdmin
)是什么意思?
def before_load(&block)
ActiveSupport::Notifications.subscribe(
ActiveAdmin::Application::BeforeLoadEvent,
&ActiveAdmin::Event.wrap_block_for_active_support_notifications(block)
)
end
答案 0 :(得分:4)
在函数&
'splats'块中(也在其上调用to_proc
),类似于常规参数的*
。
这有点等同于
def before_load(&block) # this binds provided block into block variable
ActiveSupport::Notifications.subscribe(ActiveAdmin::Application::BeforeLoadEvent){|some_params_maybe|
ActiveAdmin::Event.wrap_block_for_active_support_notifications(block).call(some_params_maybe)
}
end
答案 1 :(得分:2)
&
调用to_proc
对象的方法,例如gets.split.map(&:to_i)
用于读取整数行,这与map { |e| e.to_i }
相同
在方法参数中,它出现在最后一个参数中,表示您传递给的代码块,请查看以下代码以获取详细信息。
def g
puts yield "g"
end
def h(block)
puts block.call "h"
end
def f(&block)
puts block.class # => Proc
puts block.call "f" # => hello f
g &block # => hello g passed as code block
h block # => hello h passed as proc
end
f { |x| "hello " + x }
答案 2 :(得分:1)
Following article对'&'的使用提供了很好的解释在Ruby中:
隐式阻止 Ruby中的方法可以通过各种有趣的方式获取参数。一个特别有趣的案例是Ruby方法占用了一个块。
事实上,所有Ruby方法都可以隐式地占用一个块,而不需要在参数列表中指定它或者必须在方法体中使用块,例如:
def hello
end
hello do
puts "hello"
end
这将毫无困难地执行,但由于我们没有执行我们传入的块,因此不打印任何内容。当然,我们可以轻松地通过yielding
执行块:< / p>
def hello
yield if block_given?
end
hello do
puts "hello"
end
这次我们得到一些输出:
hello
我们yielded
到方法内的块,但是方法占用块的事实仍然是隐含的。
由于Ruby允许将任何对象传递给方法并让该方法尝试将此对象用作其块,因此它变得更加有趣。如果我们在方法的最后一个参数前放置一个&符号,Ruby将尝试将此参数视为方法的块。如果参数已经是Proc对象,Ruby将简单地将它与方法相关联作为其块。
def hello
yield if block_given?
end
blah = -> {puts "lambda"}
hello(&blah)
lambda
如果参数不是Proc
,那么 Ruby会尝试将其转换为一个(通过调用to_proc),然后将其与方法关联作为其块。
def hello
yield if block_given?
end
class FooBar
def to_proc
-> {puts 'converted lambda'}
end
end
hello(&FooBar.new)
converted lambda
所有这一切看起来都非常清楚,但是如果我想采用与方法相关联的块并将其传递给另一个方法呢?我们需要一种方法来引用我们的块。
明确的阻止 当我们编写方法定义时,我们可以明确声明我们希望这个方法可能需要一个块。令人困惑的是,Ruby也使用了&符号:
def hello(&block)
yield if block_given?
end
hello do
puts "hello"
end
以这种方式定义我们的方法,给我们一个名称,通过该名称我们可以在方法体中引用我们的块。由于我们的块是Proc
对象,而不是yielding
,我们可以call
:
def hello(&block)
block.call if block_given?
end
hello do
puts "hello"
end
我更喜欢block.call
而不是yield
,这会让事情更清晰。当然,当我们定义我们的方法时,我们不必使用名称'block',我们可以这样做:
def hello(&foo)
foo.call if block_given?
end
hello do
puts "hello"
end
说完了; 'block'是一个很好的约定。