Topic: blocks, yield

i have a helper

  def unordered_list_tree(tree, parent_id=nil)
    ret = "\n<ul>"
    tree.each do |node|
      if node.parent_id == parent_id
        ret += "\n\t<li>"
        ret += yield node
        ret += unordered_list_tree(tree, { |n| yield n } unless node.children.empty?
        ret += "\t</li>\n"
    ret += "</ul>\n"

and in views i write

<%= unordered_list_tree(@categories) do |category|
    (link_to, :action => 'show') + " " +
    (link_to 'Up',   {:action => 'move_up',   :id => category}, {:class => 'move-up'}  unless category.first?).to_s + " " +
    (link_to 'Down', {:action => 'move_down', :id => category}, {:class => 'move-down'} unless category.last?).to_s

is it possible to write something like this ?

<% unordered_list_tree(@categories) do |category| %>
  Hello, ...
  <%= link_to, :action => 'show') %>
  <%= link_to 'Up',   {:action => 'move_up',   :id => category}, {:class => 'move-up'}  unless category.first? %>
  <%= link_to 'Down', {:action => 'move_down', :id => category}, {:class => 'move-down'} unless category.last? %>
<% end %>

Re: blocks, yield

Yes, there are a few built in ruby helpers that do this type of block syntax (such as form_for). It behaves a little strangely though.

From my understanding, when calling "yield" with this kind of block, the output isn't returned from the yield, instead it is output directly as the page content. This means you can't put the output into a variable in the helper method.

How do you output something before/after the block then? By using the concat method. Here's the end result.

  def unordered_list_tree(tree, parent_id=nil)
    tree.each do |node|
      if node.parent_id == parent_id
        yield node
        # try it without this line first, you'll probably have to rework this because the result of the yield
        # isn't returned and therefore cannot be passed to another block AFAIK
        #unordered_list_tree(tree, { |n| yield n } unless node.children.empty?
        # you may be able to do this if you specify &block as an incoming parameter at the top of this function:
        # unordered_list_tree(tree,, &block)

Does that work?

Railscasts - Free Ruby on Rails Screencasts