Spec-Zone.ru › Ruby on Rails 7.0

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

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

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