How do I create a helper with block?

so two things that are important:

  • rails ignores anything that isn't a string in a content_tag (and content_for)
  • you can't use Array#join (etc.) because it produces unsafe strings, you need to use safe_join and content_tag to have safe strings
  • I didn't need either capture or concat in my case.
  def map_join(objects, &block)
    safe_join(objects.map(&block))
  end

  def list(objects, &block)
    if objects.none?
      content_tag(:p, "none")
    else
      content_tag(:ul, class: "disc") do
        map_join(objects) do |object|
          content_tag(:li) do
            block.call(object)
          end
        end
      end
    end
  end

this can be used like this:

= list(@users) do |user|
  => render user
  = link_to "show", user 

(this is slim but works fine with erb too)


You should use CaptureHelper.

def my_div(some_options, &block)
  # capture the value of the block a string
  content = capture(&block)
  # concat the value to the output
  concat(content)
end

<% my_div([]) do %>
  <p>The content</p>
<% end %>


def my_div(some_options, &block)
  # capture the value of the block a string
  # and returns it. You MUST use <%= in your view.
  capture(&block)
end

<%= my_div([]) do %>
  <p>The content</p>
<% end %>

Use capture + concat if you need to concat the output. Use capture if you need to capture and then reuse the content. If your block doesn't explicitely use <%=, then you MUST call concat (preferred way).

This is an example of a method that hides the content if the user it not an admin.

def if_admin(options = {}, &block)
  if admin?
    concat content_tag(:div, capture(&block), options)
  end
end

<% if_admin(:style => "admin") do %>
<p>Super secret content.</p>
<% end %>

http://www.rubycentral.com/book/tut_containers.html

The yield statement will return the result of the block passed. So if you wanted to print (console?)

def my_div &block
  yield
end

my_div { puts "Something" } 

Would output "Something"

But: What is the idea of your method? Outputting a DIV?