Saurabh Nanda
Saurabh Nanda

Reputation: 6793

ERB -- content_for_with_default

I am trying to reduce the repetitive code with the following pattern in an ERB template:

<% if content_for(some_key) %>
  <%= yield(some_key) %>
<% else %>
  Some default values here
<% end %>

I've tried defining the following method in ApplicationHelper but understandably it's not working as expected;

def content_for_with_default(key, &block)
  if content_for?(key)
    yield(key)
  else
    block.call
  end
end

Here's how I'm trying to use it:

<%= content_for_with_default(some_key) do %>
  Some default values here
<% end %>

How can I write the content_for_with_default helper so that it has the intended effect?

Upvotes: 0

Views: 134

Answers (1)

Yanhao
Yanhao

Reputation: 5294

Your helper should be like this:

def content_for_with_default(key, &block)
  if content_for?(key)
    content_for(key)
  else
    capture(&block)
  end
end

EDIT: difference between capture(&block) and block.call

After the erb file is compiled, the block will be some ruby code like this:

');@output_buffer.append=  content_for_with_default('some_key') do @output_buffer.safe_concat('
');
@output_buffer.safe_concat('  Some default values here
'); end 

You see, the strings within the block are concatenated to the output_buffer and safe_concate returns the whole output_buffer.

As a result, block.call also returns the whole output_buffer. However, capture(&block) creates a new buffer before calling the block and only returns the content of the block.

Upvotes: 1

Related Questions