Spec-Zone.ru › Ruby on Rails 5.0

класс ActionView::PartialRenderer

Родитель:
ActionView::AbstractRenderer
Включенные модули:
ActionView::CollectionCaching

Частичные представления 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 между каждым частичным шаблоном ad:

<%= render partial: "ad", collection: @advertisements, spacer_template: "ad_divider" %>

Если переданный :collection равен null или пуст, render вернёт null. Это позволит вам указать текст, который будет отображаться вместо него, используя такой формат:

<%= render(partial: "ad", collection: @advertisements) || "There's no ad to be displayed" %>

ПРИМЕЧАНИЕ: Из-за проблем с обратной совместимостью коллекция не может быть массивом хешей. Обычно вы бы хранили только объекты домена, такие как Active Record, в ней.

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

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

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

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

Публичные методы класса

new(*) Показать исходный код
# File actionview/lib/action_view/renderer/partial_renderer.rb, line 290
def initialize(*)
  super
  @context_prefix = @lookup_context.prefixes.first
end
Вызывает метод суперкласса

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

render(context, options, block) Показать исходный код
# 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
    instrument(:partial) do
      render_partial
    end
  end
end

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

Spec-Zone.ru

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