2013-12-09 2 views
8

У меня возникают проблемы, чтобы найти способ сделать следующее:рельсы 4 макеты гнездования

Скажем, в моем application.html.erb я следующее

<div id="one" > 
    <%= yield %> 
</div> 

Тогда я хочу, чтобы иметь другое файл макета asdf.html.erb

<div id="two"> 
    <%= yield %> 
</div> 

Я хочу, чтобы конечный результат будет

<div id="one> 
    <div id="two"> 
     <%= yield %> 
    </div> 
</div> 

Возможно ли это? Благодарю.

ответ

7

По умолчанию application.html.erb ваш макет. Вы можете оказать суб-макет по умолчанию, вызвав его в качестве частичной из макета приложения:

# app/views/layouts/application.html.erb 
<div id="one" > 
    <%= render "layouts/asdf" %> 
</div> 

# app/views/layouts/_asdf.html.erb 
<div id="two"> 
    <%= yield %> 
</div> 

Этот выход следующее:

<div id="one> 
    <div id="two"> 
     <%= yield %> 
    </div> 
</div> 

Альтернативно, если вы хотите условно визуализировать макеты на основе контроллера по контроллеру, вы должны рассмотреть возможность использования nested layouts. Из документации:

На страницах порожденных NewsController, вы хотите, чтобы скрыть главное меню и добавить правое меню:

# app/views/layouts/news.html.erb 
<% content_for :stylesheets do %> 
    #top_menu {display: none} 
    #right_menu {float: right; background-color: yellow; color: black} 
<% end %> 
<% content_for :content do %> 
    <div id="right_menu">Right menu items here</div> 
    <%= content_for?(:news_content) ? yield(:news_content) : yield %> 
<% end %> 
<%= render template: "layouts/application" %> 

Мнения Новости будут использовать новый макет, скрывая в верхнем меню и добавлении нового правого меню внутри div.

+0

Но как получить имя макета, который был вызван? Я бы ожидал чего-то вроде 'layout == 'application'? yield: render layout' –

8

Чистейший решение, которое я нашел далеко пришел из этого репо: https://github.com/rwz/nestive

Я не хочу, чтобы весь драгоценный камень. Если вы похожи на меня, вот как я достиг того, что я хотел:

# application_helper.rb 

    # From https://github.com/rwz/nestive/blob/master/lib/nestive/layout_helper.rb 
    def extends(layout, &block) 
    # Make sure it's a string 
    layout = layout.to_s 

    # If there's no directory component, presume a plain layout name 
    layout = "layouts/#{layout}" unless layout.include?('/') 

    # Capture the content to be placed inside the extended layout 
    @view_flow.get(:layout).replace capture(&block) 

    render file: layout 
    end 

Тогда вы держите /layouts/application.html.erb без изменений!

И вы можете создавать другие макеты. В моем случае /layouts/public.html.erb и /layouts/devise.html.erb:

# public.html.erb 
<%= extends :application do %> 
    <%= render 'partials/navbar' %> 
    <div class="container margin-top"> 
    <%= yield %> 
    </div> 
<% end %> 

# devise.html.erb 
<%= extends :public do %> 
    <div class="col-sm-6 col-sm-offset-3"> 
    <%= yield %> 
    </div> 
<% end %> 

работает как шарм! Я все еще улыбаюсь, наконец нашел свое решение.

+0

Обнаружил ваш комментарий сегодня и сразу же нанял его. Это очень полезно, спасибо! – dimitarvp

1

Вы также можете сделать следующее условно вынести суб-макет:

# app/views/layouts/application.html.erb 
<%= controller.controller_name.include?("foo") ? render("layouts/foo") : yield %> 

# app/views/layouts/_foo.html.erb 
<div class="bar"> 
    <%= yield %> 
</div> 

Для сценариев только с одной субом-макетом, я считаю, это предпочтительнее вложенным подход макета, изложенным в Rails guide, потому что исполнение не нужно переходить из подмашины, в основной макет, а затем обратно в подмакет. Вместо этого он протекает более естественно, начиная с основного макета, переходя к суб-макету, а затем заканчивая на представлении.

0

Если вы ищете чистое решение, которое не связывает application.html.erb с его унаследовавшими элементами, то жемчужина (как указано в другом, используется для этого, но, похоже, не работает с Rails 5. Но это еще один способ сделать это:. https://mattbrictson.com/easier-nested-layouts-in-rails

# Place this in app/helpers/layouts_helper.rb 
module LayoutsHelper 
    def parent_layout(layout) 
    @view_flow.set(:layout, output_buffer) 
    output = render(:file => "layouts/#{layout}") 
    self.output_buffer = ActionView::OutputBuffer.new(output) 
    end 
end 

Тогда asdf.html.erb становится

<div id="two"> 
    <%= yield %> 
</div> 
<% parent_layout 'application' %> 

Имейте в виду, что это зависит от Rails внутренностей и он может перестать работать в будущей версии этой скорее всего, не скоро произойдет, так как это работает минимум 3 года (в зависимости от даты связанного сообщения в блоге).

Смежные вопросы