Reputation: 5840
I want to make a helper like the following.
def my_div some_options, &block # How do I print the result of the block? end
Upvotes: 15
Views: 5534
Reputation: 1895
so two things that are important:
content_tag
(and content_for
)Array#join
(etc.) because it produces unsafe strings, you need to use safe_join
and content_tag
to have safe stringscapture
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)
Upvotes: 2
Reputation: 5767
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?
Upvotes: 1
Reputation: 176552
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 %>
Upvotes: 26