Spec-Zone.ru › Ruby on Rails 7.2

класс 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>

Текущий рендерируемый объект, а также объект_счётчик, будут доступны как локальные переменные внутри шаблона макета под теми же именами, что и в частичном представлении.

Можно также применить макет к блоку внутри любого шаблона:

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