Home » Ruby » What are those pipe symbols for in Ruby?

What are those pipe symbols for in Ruby?

Posted by: admin November 30, 2017 Leave a comment

Questions:

What are the pipe symbols for in Ruby?

I’m learning Ruby and RoR, coming from a PHP and Java background, but I keep coming across code like this:

def new 
  @post = Post.new

  respond_to do |format|
    format.html # new.html.erb
    format.xml { render :xml => @post }
  end
end

What is the |format| part doing? What’s the equivalent syntax of these pipe symbols in PHP/Java?

Answers:

They are the variables yielded to the block.

def this_method_takes_a_block
  yield(5)
end

this_method_takes_a_block do |num|
  puts num
end

Which outputs “5”. A more arcane example:

def this_silly_method_too(num)
  yield(num + 5)
end

this_silly_method_too(3) do |wtf|
  puts wtf + 1
end

The output is “9”.

Questions:
Answers:

This was very strange to me too at first, but I hope this explanation/walkthru helps you.

The documentation touches the subject, in a quite good way – if my answer doesn’t help I am sure their guide will.

First, fire up the Interactive Ruby interpreter by typing irb in your shell and hitting Enter.

Type something like:

the_numbers = ['ett','tva','tre','fyra','fem'] # congratulations! You now know how to count to five in Swedish.

just so that we have an array to play with. Then we create the loop:

the_numbers.each do |linustorvalds|
    puts linustorvalds
end

It will output all the numbers, separated by newlines.

In other languages you’d have to write something like:

for (i = 0; i < the_numbers.length; i++) {
    linustorvalds = the_numbers[i]
    print linustorvalds;
}

The important things to note are that the |thing_inside_the_pipes| can be anything, as long as you are using it consistently. And understand that it is loops we are talking about, that was a thing I didn’t get until later on.

Questions:
Answers:

The code from the do to the end defines a Ruby block. The word format is a parameter to the block. The block is passed along with the method call, and the called method can yield values to the block.

See any text on Ruby for details, this is a core feature of Ruby that you will see all the time.

Questions:
Answers:
@names.each do |name|
  puts "Hello #{name}!"
end

at http://www.ruby-lang.org/en/documentation/quickstart/4/ is accompanied by this explanation:

each is a method that accepts a block of code then runs that block of code for every element in a list, and the bit between do and end is just such a block. A block is like an anonymous function or lambda. The variable between pipe characters is the parameter for this block.

What happens here is that for every entry in a list, name is bound to that list element, and then the expression puts "Hello #{name}!" is run with that name.

Questions:
Answers:

The equivalent in Java would be something like

// Prior definitions

interface RespondToHandler
{
    public void doFormatting(FormatThingummy format);
}

void respondTo(RespondToHandler)
{
    // ...
}

// Equivalent of your quoted code

respondTo(new RespondToHandler(){
    public void doFormatting(FormatThingummy format)
    {
        format.html();
        format.xml();
    }
});

Questions:
Answers:

Parameters for a block sit between the | symbols.

Questions:
Answers:

To make it even more clearer, if needed:

the pipe bars essentially make a new variable to hold the value generated from the method call prior. Something akin to:

Original definition of your method:

def example_method_a(argumentPassedIn)
     yield(argumentPassedIn + 200)
end

How It’s used:

example_method_a(100) do |newVariable|
    puts newVariable;
end

It’s almost the same as writing this:

newVariable = example_method_a(100) 
puts newVariable

where, newVariable = 200 + 100 = 300 :D!