Spec-Zone.ru › Ruby on Rails 8.1

class 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, которому в качестве локальной переменной account будет передан @buyer, а затем отобразится advertiser/_ad.html.erb, которому будет передана локальная переменная ad для отображения в шаблоне.

Параметры :as и :object

По умолчанию ActionView::PartialRenderer не имеет локальных переменных. Параметр :object можно использовать для передачи объекта частичному шаблону. Например:

<%= render partial: "account", object: @buyer %>

объект @buyer будет передан частичному шаблону и доступен в локальной переменной account. Это эквивалентно следующему:

<%= render partial: "account", locals: { account: @buyer } %>

С помощью параметра :as можно указать другое имя для этой локальной переменной. Например, если вместо account мы хотим использовать user, то напишем:

<%= render partial: "account", object: @buyer, as: 'user' %>

Это эквивалентно следующему:

<%= render partial: "account", locals: { user: @buyer } %>

Отображение вариантов частичного шаблона

Параметр :variants можно использовать для отображения другого варианта шаблона частичного шаблона. Например:

<%= render partial: "account", variants: :mobile %>

Будет отображён _account.html+mobile.erb. Этот параметр также принимает несколько вариантов, например:

<%= render partial: "account", variants: [:desktop, :mobile] %>

Будут проверены следующие шаблоны, и отобразится первый из существующих:

  • _account.html+desktop.erb

  • _account.html+mobile.erb

  • _account.html.erb

Отображение коллекции частичных шаблонов

В примере использования частичных шаблонов описан знакомый шаблон, в котором шаблону нужно перебрать массив и отобразить подшаблон для каждого элемента. Этот шаблон реализован в виде единственного метода, который принимает массив и отображает частичный шаблон с тем же именем, что и у содержащихся в массиве элементов. Таким образом, трёхстрочный пример из раздела «Использование частичных шаблонов» можно переписать одной строкой:

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

Отображение в стандартном случае

Если вы не собираетесь использовать такие параметры, как коллекции или макеты, для отображения частичных шаблонов можно также использовать сокращённые варианты вызова 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>

Если имена двух пользователей — Alice и Bob, эти фрагменты вернут:

<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 общий для частичного шаблона и его макета.

Открытые методы класса

new (lookup_context, options) Показать исходный код
# File actionview/lib/action_view/renderer/partial_renderer.rb, line 239
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 246
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–2021 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

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