简体   繁体   中英

Extending an existing layout in Rails

I have my main application layout, but then I have an /account section of my site which has exactly the same layout as the application layout markupwise, except the /account pages have an added sidebar in the content area of the layout.

Rather than blatantly copy the application layout and create a nearly redundant "account" layout, I'd like to extend the application layout, adding the sidebar in the content area.

So I have something like this in my application layout:

<html>
<body>

<div id="content">

<%= yield %>

</div>

</body>
</html>

and I want

<html>
<body>

<div id="content">

  <div id="sidebar"></div>

  <%= yield %>

</div>

</body>
</html>

Is there a way to accomplish this without copying code?

You can have more than one yield in a layout, simply give the additional ones a name:

<html>
<body>
  <div id="content">
    <%= yield :sidebar %>
    <%= yield %>
  </div>
</body>
</html>

You can add HTML for that yield by using the content_for method

<% content_for :sidebar do -%>
  <div id="sidebar"></div>
<% end -%>

But you'll have to add that to every view you want to have a sidebar. Instead, create views/layouts/application_with_sidebar.html.erb

<% content_for :sidebar do -%>
  <div id="sidebar"></div>
<% end -%>

<%= render :file => 'layouts/application' %>

Further reading

If you'd prefer to keep the number of yield s to a minimum, you can nest your layouts instead.

views/layouts/application.html.erb

<html>
<body>
  <div id="content">
    <%= yield(:with_sidebar) or yield %>
  </div>
</body>
</html>

views/layouts/application_with_sidebar.html.erb

<% content_for :with_sidebar do -%>
  <div id="sidebar"></div>
<% end -%>

<%= render :file => 'layouts/application' %>

controllers/accounts_controller.rb

class AccountsController < ApplicationController
  layout 'application_with_sidebar'
  ...
end

Often you'll have the same situation for other parts of the site in which case it may make sense to use nested layouts.

http://guides.rubyonrails.org/v2.3.8/layouts_and_rendering.html#using-nested-layouts

If your /account route is bound to the account controller, you can always have a fullfeatured layout with conditional part like this

render :template => "/shared/sidebar" if controller.controller_name == "account"

(I have to admit that it does not please the eye though)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM