What are those pipe symbols for in Ruby?

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?

38421 次浏览

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.

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();
}
});

Parameters for a block sit between the | symbols.

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

@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.

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.

为了更清楚地说明这一点,如果需要:

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!