Spec-Zone.ru › Ruby on Rails 6.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>

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

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

<%# 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
ИМЕНА_ЧАСТИЧНЫХ_ПРЕДСТАВЛЕНИЙ_С_ПРЕФИКСОМ

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

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

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

render(context, options, block) Показать исходный код
# File actionview/lib/action_view/renderer/partial_renderer.rb, line 294
def render(context, options, block)
  as = as_variable(options)
  setup(context, options, as, block)

  if @path
    if @has_object || @collection
      @variable, @variable_counter, @variable_iteration = retrieve_variable(@path, as)
      @template_keys = retrieve_template_keys(@variable)
    else
      @template_keys = @locals.keys
    end
    template = find_partial(@path, @template_keys)
    @variable ||= template.variable
  else
    if options[:cached]
      raise NotImplementedError, "render caching requires a template. Please specify a partial when rendering"
    end
    template = nil
  end

  if @collection
    render_collection(context, template)
  else
    render_partial(context, template)
  end
end

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

Spec-Zone.ru

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