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
"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.
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.
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.
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
If you look around blocks are used all over the place, especially in iterators, like Array#each
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With