在这个ruby语句中,“break”做了什么

时间:2013-07-19 22:21:52

标签: ruby

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

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

问题在于.tap {}后代码阻塞了什么?特别是最初的“休息”对我来说很奇怪。

3 个答案:

答案 0 :(得分:7)

块中的

break argument会导致块返回argument。默认情况下,tap返回与给定的对象相同的对象,但中断将导致它返回o.send(version) if version求值的任何内容。

答案 1 :(得分:3)

#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管道,但有机会随时访问数据。像一个水龙头。

它应该采取一些东西并将相同的东西返回到管道的下一部分。

但是,使用break 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

答案 2 :(得分:1)

来自文档:

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

因此,代码的含义是在某些条件下更改tap的值:

  • 如果版本为true,那么break会将o.send(version)的结果带到下一个链。
  • 否则它只会带来tap
  • 的传入值