Spec-Zone.ru › Ruby on Rails 6.1

класс ActionView::PartialRenderer

Родитель:
ActionView::AbstractRenderer

Частичные представления 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" %>

Рендеринг общих частичных представлений

Два контроллера могут использовать набор частичных представлений и рендерить их так:

<%= 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 %>

Рендеринг по умолчанию

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

# 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», они будут переданы в блок. Один из способов использования этого — передать массив в макет и обращаться с ним как со структурой перечисления.

END_OF_DOCUMENT_MARKER
<%# 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 %>

Методы публичного класса

new(lookup_context, options) Показать исходный код
# File actionview/lib/action_view/renderer/partial_renderer.rb, line 257
def initialize(lookup_context, options)
  super(lookup_context)
  @options = options
  @locals  = @options[:locals] || {}
  @details = extract_details(@options)
end
Вызывает метод суперкласса

Методы публичного экземпляра

render(partial, context, block) Показать исходный код
# File actionview/lib/action_view/renderer/partial_renderer.rb, line 264
def render(partial, context, block)
  template = find_template(partial, template_keys(partial))

  if !block && (layout = @options[:layout])
    layout = find_template(layout.to_s, template_keys(partial))
  end

  render_partial_template(context, @locals, template, layout, block)
end

© 2004–2020 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API