Многоуровневая вложенная компоновка в Rails 3
У меня есть приложение с файлом макета глобального приложения application.html.haml
. Затем у меня есть несколько "стеков контроллера": для нашего основного сайта, нашего портала-администратора и нашего бизнес-сайта. Для каждого из них контроллеры находятся внутри модуля и все наследуются от одного и того же BaseController
. Каждый стек имеет собственный файл макета. Внутри стека некоторые контроллеры также имеют файлы макета.
Я бы хотел, чтобы все представления (если не указано иное) отображались внутри нескольких уровней вложенных макетов: приложение, "стек", "контроллер".
Например, для действия Site::BlogController#show
я бы хотел, чтобы рельсы отображались:
/site/blog/show.html.haml
внутри /layouts/site/blog.html.haml
внутри /layouts/site.html.haml
внутри /layouts/application.html.haml
Мне трудно понять, как вставить /layouts/site.html.haml
в стек. Кажется, что автоматически, рельсы будут отображать действие внутри макета контроллера внутри макета приложения, однако я не вижу, как "вставлять" макеты в стек рендеринга.
Любая помощь очень приветствуется, однако, я прочитал все руководства по направляющим, но ничего не получилось, поэтому ссылка на http://guides.rubyonrails.org/layouts_and_rendering.html#using-nested-layouts не будет действительно будет полезно.
Ответы
Ответ 1
Я перечитал ссылку, которую я опубликовал (http://guides.rubyonrails.org/layouts_and_rendering.html#using-nested-layouts), и понял, что я пропустил ключевую деталь.
<%= render :file => 'layouts/application' %>
поэтому в Site::BaseController
у меня есть вызов layout 'site'
, а в /layouts/site.html.haml
у меня есть
= content_for :footer do
-#Content for footer
= render :file => 'layouts/application'
Тогда в Site::BlogController
, который продолжается Site::BaseController
, я layout 'site/blog'
и в /layouts/site/blog.html.haml
имеет
=content_for :header do
%h1 HELLO WORLD!
= render :file => 'layouts/site'
Затем это делает макеты вложенными, как описано в вопросе. Извините за отсутствие этого в моем вопросе. Я должен был читать ближе.
Ответ 2
если вы создаете вспомогательный помощник:
# renders a given haml block inside a layout
def inside_layout(layout = 'application', &block)
render :inline => capture_haml(&block), :layout => "layouts/#{layout}"
end
то вы можете определить sublayout следующим образом:
= inside_layout do
# nested layout html here
= yield
эти макеты могут использоваться как обычные макеты.
подробнее: http://www.requests.ch/blog/2013/10/30/combine-restful-rails-with-nested-layouts/
Ответ 3
Я сделал аналогичный, но использовал только 1 уровень подуровней. Можно легко настроить, чтобы разрешить несколько уровней.
В контроллерах /application _controller.rb:
def sub_layout
nil
end
В контроллере (например, blog_controller.rb):
def sub_layout
"blog"
end
В layouts/application.html.erb вместо <%=yield%>
:
<%= controller.sub_layout ? (render :partial => "/layouts/#{controller.sub_layout}") : yield %>
Сделайте частичный layouts/_blog.html.erb
:
...code
<%=yield%>
...code
Повторите это для других макетов контроллера и подкомпоновки.
EDIT:
Если вам нужно сделать это на основе действия:
def sub_layout
{
'index' => 'blog',
'new' => 'other_sub_layout',
'edit' => 'asdf'
}[action_name]
end
Ответ 4
Я думаю, что самый простой способ сделать это - добавить эту строку кода в родительский элемент вложенного макета:
((render "layouts/#{controller_name}" rescue nil)|| yield )
вы можете добавить столько вложенных макетов, сколько хотите, только изменив каталог пути следующего макета, который будет отображаться.
note: убедитесь, что ваш вложенный макет назван _layoutname.whatever и что ваш вложенный макет имеет yield внутри
Ответ 5
Вы можете создать частичный с уроком в нем.
_my_sub_layout.html.erb:
<h3>I'm a sub layout and here my content:</h3>
<%= yield %>
В каком-то другом представлении или даже в вашем основном макете application.html.erb отображает частичное как макет:
<%= render layout: 'my_sub_layout' do %>
<p>I'm the sub layout content</p>
<% end %>