класс 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 %>
Это отобразит макет для каждого пользователя и вызовет блок, каждый раз передавая пользователя.
Вы также можете вызывать yield несколько раз в одном макете и использовать аргументы блока для различения разделов.
<%# 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
- PREFIXED_PARTIAL_NAMES
Публичные методы класса
# File actionview/lib/action_view/renderer/partial_renderer.rb, line 290 def initialize(*) super @context_prefix = @lookup_context.prefixes.first end
Публичные методы экземпляра
# File actionview/lib/action_view/renderer/partial_renderer.rb, line 295
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.