Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's this &block in Ruby? And how does it get passed in a method here?

Saw this piece of code in a Ruby on Rails book. This first one is from a view and the second one is a helper module. I don't understand how that &block and the attributes={} thing work. Can anyone guide me to a tutorial of some kind explaining this?

<% hidden_div_if(@cart.items.empty?, :id => "cart") do %>  <%= render(:partial => "cart", :object => @cart) %> <% end %>  module StoreHelper  def hidden_div_if(condition, attributes = {}, &block)   if condition    attributes["style"] = "display: none"   end    content_tag("div", attributes, &block)   end end 
like image 840
Malik Daud Ahmad Khokhar Avatar asked May 02 '09 12:05

Malik Daud Ahmad Khokhar


People also ask

Whats this Whats this Disney?

"What's This?" is a song from the film, The Nightmare Before Christmas sung by Jack as he is exploring Christmas Town as he discovers something the citizens of Christmas Town do differently than the citizens of Halloween Town do differently. A reprisal of the song was sung when Santa made it snow in Halloween Town.

What is this Jack Skellington?

Jack Skellington is a character and the main protagonist of the 1993 film The Nightmare Before Christmas. He is a skeletal zombie who is the Pumpkin King of Halloween Town, a fantasy world based solely on the Halloween holiday.

What's this The Nightmare Before Christmas Wiki?

The Nightmare Before Christmas (also known as Tim Burton's The Nightmare Before Christmas) is a 1993 American stop-motion animated musical dark fantasy film directed by Henry Selick (in his feature directorial debut) and produced and conceived by Tim Burton.


2 Answers

Blocks are a fairly basic part of ruby. They're delimited by either do |arg0,arg1| ... end or { |arg0,arg1,arg2| ... }.

They allow you to specify a callback to pass to a method. This callback can be invoked two ways - either by capturing it by specifying a final argument prefixed with &, or by using the yield keyword:

irb> def meth_captures(arg, &block)        block.call( arg, 0 ) + block.call( arg.reverse , 1 )      end #=> nil irb> meth_captures('pony') do |word, num|        puts "in callback! word = #{word.inspect}, num = #{num.inspect}"        word + num.to_s      end in callback! word = "pony" num = 0 in callback! word = "ynop" num = 1 #=> "pony0ynop1"  irb> def meth_yields(arg)        yield(arg, 0) + yield(arg.upcase, 1)      end #=> nil irb> meth_yields('frog') do |word, num|        puts "in callback! word = #{word.inspect}, num = #{num.inspect}"        word + num.to_s      end in callback! word = "frog", num = 0 in callback! word = "FROG", num = 1 #=> "frog0FROG1" 

Note that our callback was the same in each case - we can remove repetition by saving our callback in an object, and then passing it to each method. This can be done using lambda to capture the callback in an object, and then passed to a method by prefixing it with &.

irb> callback = lambda do |word, num|        puts "in callback! word = #{word.inspect}, num = #{num.inspect}"        word + num.to_s      end #=> #<Proc:0x0052e3d8@(irb):22> irb> meth_captures('unicorn', &callback) in callback! word = "unicorn", num = 0 in callback! word = "nrocinu", num = 1 #=> "unicorn0nrocinu1" irb> meth_yields('plate', &callback) in callback! word = "plate", num = 0 in callback! word = "PLATE", num = 1 #=> "plate0PLATE1" 

It's important to understand the different uses of & here as a prefix to the last argument of a function

  • in a function definition, it captures any passed block into that object
  • in a function call, it expands the given callback object into a block

If you look around blocks are used all over the place, especially in iterators, like Array#each.

like image 190
rampion Avatar answered Oct 05 '22 23:10

rampion


The &block is a way of sending a piece of Ruby code in to a method and then evaluating that code in the scope of that method. In your example code above it means a partial named cart will be rendered in a div. I think the term closure is used for this in computer science.

So in your example the &block is:

<%= render(:partial => "cart", :object => @cart) %> 

Some good reading and an explanation of blocks, procs and lamdas can be found at Robert Sosinski's blog.

like image 35
gaqzi Avatar answered Oct 06 '22 01:10

gaqzi