Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Partial with multiple yields in rails

I'm looking for solution to have partial with multiple yields.

In real example I have this views structure:

Basic application.erb (/views/layouts/application.erb):

<!DOCTYPE html>
<head>
    <title>Some title</title>
</head>
<body>
<div class="page">
    <%= yield %>
</div>
</body>
</html> 

Some partial to DRY my code (/views/shared/content.erb):

<div class="content">
    <div class="sidebar">
        <%= yield :sidebar %>
    </div>
    <div class="main">
        <%= yield %>
    </div>
</div>

And controller view (/views/home/index.erb):

<%= render :partial => 'layouts/header' %>    
<%= render :partial => 'shared/navigation' %>

<% # It is close to what I want to do %>
<%= render :layout => 'shared/content' do %>
    <% content_for :sidebar do %>
        <%# This is will go to application.erb, not in content.erb %>
        <%= render :partial => 'shared/menu' %>
    <% end %>

    <%= yield %>
<% end %>

<%= render :partial => 'layouts/footer' %>

So the main issue here is to have a template block with multiple yield areas and ability to pass custom html or render another partial.

like image 803
a.s.panchenko Avatar asked Jun 21 '13 10:06

a.s.panchenko


People also ask

What is the reason for having partials in Rails?

A partial allows you to separate layout code out into a file which will be reused throughout the layout and/or multiple other layouts. For example, you might have a login form that you want to display on 10 different pages on your site.

What are Rails partials?

Rails Guides describes partials this way: Partial templates - usually just called "partials" - are another device for breaking the rendering process into more manageable chunks. With a partial, you can move the code for rendering a particular piece of a response to its own file.

What is yield tag in Rails?

Without any arguments, yield will render the template of the current controller/action. So if you're on the cars/show page, it will render views/cars/show. html. erb . When you pass yield an argument, it lets you define content in your templates that you want to be rendered outside of that template.

How can you tell Rails to render without a layout?

By default, if you use the :plain option, the text is rendered without using the current layout. If you want Rails to put the text into the current layout, you need to add the layout: true option and use the . text. erb extension for the layout file.


2 Answers

This question is old, however, it's still relevant when I was searching for an answer on Google.

I've come up with a solution, while still not beautiful, works very well. The idea uses Rails' capture method, which takes a block and stores its contents into a variable:

controller.html.erb

<%= render 'shared/partial', body: capture { %>
  My body content
<% }, footer: capture { %>
  My footer content
<% } %>

shared/_partial.html.erb

<div id="body"><%= body %></div>
<div id="footer"><%= footer %></div>

Hope this helps someone!

like image 103
Wes Foster Avatar answered Oct 16 '22 18:10

Wes Foster


In my case I've found solution like this.

On my controller view (/views/home/index.erb):

<% sidebar_content = render :partial => 'shared/slider' %>
<%= render :layout => 'shared/content', :locals => {:sidebar => sidebar_content} do %>
    <%= yield %>
<% end %>

The partial with multiple areas (/views/shared/content.erb):

<div class="content">
    <div class="sidebar">
        <%= sidebar %>
    </div>
    <div class="main">
        <%= yield %>
    </div>
</div>

This solution doesn't look pretty, but it works. I hope to find something better in near future.

like image 3
a.s.panchenko Avatar answered Oct 16 '22 17:10

a.s.panchenko