4

此代码片段来自 plataformecs gem simple_form,关于“添加自定义输入”的 wiki 部分:

out << template.image_tag(object.send(attribute_name).tap {|o| break o.send(version) if version}.send('url'))

问题只是 .tap {} 之后的代码块是什么意思?特别是最初的“休息”,这对我来说看起来很奇怪。

4

3 回答 3

12

break argument在一个块中导致块返回argument。默认情况下,tap返回与给定对象相同的对象,但中断将导致它返回任何o.send(version) if version计算结果。

于 2013-07-19T22:41:01.553 回答
4

#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
于 2013-07-19T22:34:42.850 回答
1

从文档中:

The break terminates a method with an associated block 
if called within the block.

所以代码的意思是tap在某些条件下改变 的值:

  • 如果版本为真,那么break将把o.send(version).
  • 否则它只会带来 的传入值tap
于 2013-07-19T22:37:21.090 回答