Search code examples
ruby-on-railsrubycontent-forcontent-tag

How do you pass local variables to a content_tag or content_for?


In my view, I have a content_tag that looks like so:

<% content_tag :div do %>
    <h1><%= title %></h1>
    <p><%= description %></p>
    ... # a bunch of other stuff
<% end %>

I'd like to use this content_tag multiple times to create "sections" on the page, each time passing a different title and description to it. However, I don't want to go and make a partial, that seems like overkill. I want everything to be contained in the one view file. How can I do it?


Solution

  • Assigning the content_tag to a variable (and subsequently printing the variable) seems a bit convoluted, particularly as there's no good way of passing your collection of products to it.

    A DRYer way of doing this would be to iterate through your list of products and pass each to your content_tag:

    <% products.each do |product| %>
        <%= content_tag :div, :class => "product-info" do %>
            <h1><%= product.name %></h1>
            <p><%= product.description %></p>
        <% end %>
    <% end %>
    

    Alternatively, you can abstract this logic into a view helper that effectively produces the same result:

    def product_info_div(products)
        products.each do |product| %>
            content_tag :div, :class => "product-info" do %>
                content_tag :div, product.name
                content_tag :p, product.description
            end
        end
    end
    

    In your view, you'd invoke this in the following manner:

    <%= product_info_div(@products) %>
    

    While this isn't a partial, it is another file. However, it's also precisely what view helpers are meant to do. Either option will keep your code DRY and readable while accomplishing precisely what you want, IMO.

    EDIT:

    You don't need to explicitly pass local variables in order to use them within a content_tag – they're available for use within the content_tag as they'd be outside of it.

    Though I'm unsure how you're precisely getting title and description to vary, you could make a parallel assignment directly prior to the content_tag declaration in which you assign values to the title and description local variables:

    <% title, description = 'title_1', 'description_1' %>
    <%= content_tag :div do %>
        <h1><%= title %></h1>
        <p><%= description %></p>
        # a bunch of other stuff
    <% end %>
    
    <% title, description = 'title_2', 'description_2' %>
    <%= content_tag :div do %>
        <h1><%= title %></h1>
        <p><%= description %></p>
        # a bunch of other stuff
    <% end %>
    

    Note that you'll need to output the content_tag using <%= %>. Rails can't do anything with an interpreted content_tag if it's not outputted.