класс ActionView::PartialRenderer
Частичные представления Action View
Также есть удобный метод для рендеринга подшаблонов внутри текущего контроллера, который зависит от одного объекта (мы называем такие подшаблоны частичными представлениями). Он полагается на то, что частичные представления должны следовать соглашению об именовании, начинаться с нижнего подчеркивания — чтобы отделить их от обычных шаблонов, которые можно рендерить самостоятельно.
В шаблоне для Advertiser#account:
<%= render partial: "account" %>
Это рендерило бы “advertiser/_account.html.erb”.
В другом шаблоне для Advertiser#buy, у нас может быть:
<%= render partial: "account", locals: { account: @buyer } %>
<% @advertisements.each do |ad| %>
<%= render partial: "ad", locals: { ad: ad } %>
<% end %> Это сначала рендерило бы advertiser/_account.html.erb с @buyer, переданным в качестве локальной переменной account, затем рендерило бы advertiser/_ad.html.erb и передавало локальную переменную ad в шаблон для отображения.
Параметры :as и :object
По умолчанию ActionView::PartialRenderer не имеет локальных переменных. Параметр :object может быть использован для передачи объекта в частичное представление. Например:
<%= render partial: "account", object: @buyer %>
передаст объект @buyer в частичное представление, доступное под локальной переменной account и эквивалентно:
<%= render partial: "account", locals: { account: @buyer } %> С помощью параметра :as мы можем указать другое имя для этой локальной переменной. Например, если мы хотим, чтобы это было user вместо account, мы сделаем:
<%= render partial: "account", object: @buyer, as: 'user' %>
Это эквивалентно
<%= render partial: "account", locals: { user: @buyer } %> Рендеринг коллекции частичных представлений
Пример использования частичных представлений описывает знакомый шаблон, где шаблон должен перебирать массив и рендерить подшаблон для каждого элемента. Этот шаблон реализован как один метод, принимающий массив и рендеринг частичного представления с тем же именем, что и содержащиеся в нем элементы. Таким образом, трехстрочный пример в “Использование частичных представлений” можно переписать в одной строке:
<%= render partial: "ad", collection: @advertisements %>
Это рендерит advertiser/_ad.html.erb и передаст локальную переменную ad в шаблон для отображения. Объект итерации автоматически станет доступным в шаблоне с именем в формате partial_name_iteration. Объект итерации знает, какой индекс имеет текущий объект в коллекции и общий размер коллекции. Объект итерации также имеет два удобных метода, first? и last?. В случае примера выше, шаблон получит ad_iteration. Для обратной совместимости параметр partial_name_counter все еще присутствует и сопоставляется с методом index итерации.
Параметр :as может использоваться при рендеринге частичных представлений.
Вы можете указать частичное представление, которое будет рендериться между элементами, используя параметр :spacer_template. Следующий пример рендерит advertiser/_ad_divider.html.erb между каждым частичным представлением объявления:
<%= render partial: "ad", collection: @advertisements, spacer_template: "ad_divider" %>
Если заданное значение :collection равно nil или пустое, render вернет nil. Это позволит вам указать текст, который будет отображаться вместо него, используя этот формат:
<%= render(partial: "ad", collection: @advertisements) || "There's no ad to be displayed" %>
ПРИМЕЧАНИЕ: из-за соображений обратной совместимости коллекция не может быть массивом хэшей. Обычно вы просто храните объекты домена, например, Active Records, в нем.
Рендеринг общих частичных представлений
Два контроллера могут совместно использовать набор частичных представлений и рендерить их так:
<%= render partial: "advertisement/ad", locals: { ad: @advertisement } %> Это рендерит частичное представление advertisement/_ad.html.erb независимо от того, из какого контроллера оно вызывается.
Рендеринг объектов, которые отвечают на to_partial_path
Вместо явного указания расположения частичного представления, вы также можете позволить PartialRenderer выполнить работу и выбрать правильный путь, проверив метод to_partial_path.
# @account.to_partial_path returns 'accounts/account', so it can be used to replace:
# <%= render partial: "accounts/account", locals: { account: @account} %>
<%= render partial: @account %>
# @posts is an array of Post instances, so every post record returns 'posts/post' on +to_partial_path+,
# that's why we can replace:
# <%= render partial: "posts/post", collection: @posts %>
<%= render partial: @posts %> Рендеринг по умолчанию
Если вы не будете использовать какие-либо параметры, такие как коллекции или макеты, вы также можете использовать краткие значения по умолчанию render для рендеринга частичных представлений. Примеры:
# Instead of <%= render partial: "account" %>
<%= render "account" %>
# Instead of <%= render partial: "account", locals: { account: @buyer } %>
<%= render "account", account: @buyer %>
# @account.to_partial_path returns 'accounts/account', so it can be used to replace:
# <%= render partial: "accounts/account", locals: { account: @account} %>
<%= render @account %>
# @posts is an array of Post instances, so every post record returns 'posts/post' on +to_partial_path+,
# that's why we can replace:
# <%= render partial: "posts/post", collection: @posts %>
<%= render @posts %> Рендеринг частичных представлений с макетами
Частичные представления могут иметь свои собственные макеты, примененные к ним. Эти макеты отличаются от тех, которые заданы глобально для всего действия, но они работают аналогичным образом. Представьте список с двумя типами пользователей:
<%# app/views/users/index.html.erb %>
Here's the administrator:
<%= render partial: "user", layout: "administrator", locals: { user: administrator } %>
Here's the editor:
<%= render partial: "user", layout: "editor", locals: { user: editor } %>
<%# app/views/users/_user.html.erb %>
Name: <%= user.name %>
<%# app/views/users/_administrator.html.erb %>
<div id="administrator">
Budget: $<%= user.budget %>
<%= yield %>
</div>
<%# app/views/users/_editor.html.erb %>
<div id="editor">
Deadline: <%= user.deadline %>
<%= yield %>
</div> …это вернет:
Here's the administrator: <div id="administrator"> Budget: $<%= user.budget %> Name: <%= user.name %> </div> Here's the editor: <div id="editor"> Deadline: <%= user.deadline %> Name: <%= user.name %> </div>
Если задана коллекция, макет будет рендериться один раз для каждого элемента в коллекции. Например, эти два фрагмента имеют одинаковый вывод:
<%# app/views/users/_user.html.erb %>
Name: <%= user.name %>
<%# app/views/users/index.html.erb %>
<%# This does not use layouts %>
<ul>
<% users.each do |user| -%>
<li>
<%= render partial: "user", locals: { user: user } %>
</li>
<% end -%>
</ul>
<%# app/views/users/_li_layout.html.erb %>
<li>
<%= yield %>
</li>
<%# app/views/users/index.html.erb %>
<ul>
<%= render partial: "user", layout: "li_layout", collection: users %>
</ul> В случае двух пользователей с именами Алиса и Боб, эти фрагменты возвращают:
<ul>
<li>
Name: Alice
</li>
<li>
Name: Bob
</li>
</ul> Текущий рендеринг объект, а также object_counter, будут доступны как локальные переменные внутри шаблона макета под теми же именами, что и в частичном представлении.
Вы также можете применить макет к блоку внутри любого шаблона:
<%# app/views/users/_chief.html.erb %>
<%= render(layout: "administrator", locals: { user: chief }) do %>
Title: <%= chief.title %>
<% end %> …это вернет:
<div id="administrator"> Budget: $<%= user.budget %> Title: <%= chief.name %> </div>
Как видите, хэш :locals общий как для частичного представления, так и для его макета.
Если вы передадите аргументы в “yield”, они будут переданы в блок. Один из способов использования — передать массив в макет и обращаться с ним как с перечисляемым объектом.
<%# app/views/users/_user.html.erb %> <div class="user"> Budget: $<%= user.budget %> <%= yield user %> </div> <%# app/views/users/index.html.erb %> <%= render layout: @users do |user| %> Title: <%= user.title %> <% end %>
Это рендерит макет для каждого пользователя и передает в блок, каждый раз передавая пользователя.
Вы также можете несколько раз передавать значения в макет и использовать аргументы блока, чтобы различать разделы.
<%# app/views/users/_user.html.erb %>
<div class="user">
<%= yield user, :header %>
Budget: $<%= user.budget %>
<%= yield user, :footer %>
</div>
<%# app/views/users/index.html.erb %>
<%= render layout: @users do |user, section| %>
<%- case section when :header -%>
Title: <%= user.title %>
<%- when :footer -%>
Deadline: <%= user.deadline %>
<%- end -%>
<% end %> Константы
- IDENTIFIER_ERROR_MESSAGE
- OPTION_AS_ERROR_MESSAGE
- ИМЕНА_ЧАСТИЧНЫХ_ПРЕДСТАВЛЕНИЙ_С_ПРЕФИКСОМ
Публичные методы класса
# File actionview/lib/action_view/renderer/partial_renderer.rb, line 292 def initialize(*) super @context_prefix = @lookup_context.prefixes.first end
Публичные методы экземпляра
# File actionview/lib/action_view/renderer/partial_renderer.rb, line 297
def render(context, options, block)
setup(context, options, block)
@template = find_partial
@lookup_context.rendered_format ||= begin
if @template && @template.formats.present?
@template.formats.first
else
formats.first
end
end
if @collection
render_collection
else
render_partial
end
end
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.