Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does "break" do in this ruby statement

Tags:

ruby

This code snippet is from plataformecs gem simple_form, wiki section about "adding custom inputs":

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

The question is simply what does the code block after .tap {} mean? Specifically the initial "break" which looks strange to me.

like image 532
Peter Andersson Avatar asked Dec 02 '22 22:12

Peter Andersson


2 Answers

break argument in a block causes the block to return argument. By default, tap returns the same object as it is given, but the break will instead cause it to return whatever o.send(version) if version evaluates to.

like image 156
Robert Kajic Avatar answered Jan 09 '23 16:01

Robert Kajic


#tap is a method that basically "passes along" the block to the next. It isn't supposed to "change" the flow of the method. For example

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}"}

It's sort of like a unix pipe, but has a chance to access the data as it goes along. like a tap.

It is supposed to take something and return the same thing to the next part of the pipe.

However, using break a will break out of the tap, and return a. That is, instead of returning what #tap would normally return (the same thing that it got), it would return a instead.

The use of #tap in this case is to pass values down the pipe "as normal", except when version is true; in that case it will send along o.send(version) instead.

Basically, the normal flow is

object.send(attribute_name).send('url')

and with tap, it's normally "unchanged". However, using break o.send(version), the flow is then instead

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
like image 27
Justin L. Avatar answered Jan 09 '23 16:01

Justin L.