此代码片段来自 plataformecs gem simple_form,关于“添加自定义输入”的 wiki 部分:
out << template.image_tag(object.send(attribute_name).tap {|o| break o.send(version) if version}.send('url'))
问题只是 .tap {} 之后的代码块是什么意思?特别是最初的“休息”,这对我来说看起来很奇怪。
此代码片段来自 plataformecs gem simple_form,关于“添加自定义输入”的 wiki 部分:
out << template.image_tag(object.send(attribute_name).tap {|o| break o.send(version) if version}.send('url'))
问题只是 .tap {} 之后的代码块是什么意思?特别是最初的“休息”,这对我来说看起来很奇怪。
break argument
在一个块中导致块返回argument
。默认情况下,tap
返回与给定对象相同的对象,但中断将导致它返回任何o.send(version) if version
计算结果。
#tap
是一种基本上将块“传递”到下一个的方法。它不应该“改变”方法的流程。例如
http://ruby-doc.org/core-2.0/Object.html#method-i-tap
(1..10) .tap {|x| puts "original: #{x.inspect}"}
.to_a .tap {|x| puts "array: #{x.inspect}"}
.select {|x| x%2==0} .tap {|x| puts "evens: #{x.inspect}"}
.map { |x| x*x } .tap {|x| puts "squares: #{x.inspect}"}
它有点像 unix 管道,但有机会在数据传输过程中访问数据。像水龙头一样。
它应该取一些东西并将相同的东西返回到管道的下一部分。
但是, usingbreak a
会跳出水龙头,并返回一个. 也就是说#tap
,它不会返回通常会返回的内容(与它得到的相同),而是会返回a
。
在这种情况下,使用#tap
“正常”将值传递到管道中,除非为version
真;在这种情况下,它将o.send(version)
改为发送。
基本上,正常流程是
object.send(attribute_name).send('url')
并且tap
,它通常是“不变的”。但是,使用break o.send(version)
,则流程改为
intermediate = object.send(attribute_name);
if version
return intermediate.send(version).send('url'); # ignore the result of intermediate
# and replace it with o.send(version)
else
return intermediate.send('url'); # maintain normal flow...it's like nothing
# was ever tapped
end
从文档中:
The break terminates a method with an associated block
if called within the block.
所以代码的意思是tap
在某些条件下改变 的值:
break
将把o.send(version)
.tap
。