Spec-Zone.ru › Ruby on Rails 8.1

модуль ActionView::Helpers::CaptureHelper

Вспомогательные методы захвата Action View

CaptureHelper предоставляет методы, позволяющие извлекать сгенерированную разметку, которую можно использовать в других частях шаблона или файла макета.

Он предоставляет метод для сохранения блоков в переменные с помощью capture, а также способ сохранить блок разметки для использования в макете с помощью content_for.

Кроме того, он предоставляет метод для использования с потоковыми ответами — provide. Подробнее см. в разделе ActionController::Streaming.

Открытые методы экземпляра

capture (*, **) { |*, **| ... } Показать исходный код
# File actionview/lib/action_view/helpers/capture_helper.rb, line 47
def capture(*, **, &block)
  value = nil
  @output_buffer ||= ActionView::OutputBuffer.new
  buffer = @output_buffer.capture { value = yield(*, **) }

  string = if @output_buffer.equal?(value)
    buffer
  else
    buffer.presence || value
  end

  case string
  when OutputBuffer
    string.to_s
  when ActiveSupport::SafeBuffer
    string
  when String
    ERB::Util.html_escape(string)
  end
end

Метод capture извлекает часть шаблона в виде строкового объекта. Затем этот объект можно использовать в любом месте шаблонов, макета или вспомогательных методов.

Метод capture можно использовать в шаблонах ERB…

<% @greeting = capture do %>
  Welcome to my shiny new web page!  The date and time is
  <%= Time.now %>
<% end %>

…и в шаблонах Builder (RXML).

@timestamp = capture do
  "The current timestamp is #{Time.now}."
end

Затем эту переменную можно использовать в любом другом месте. Например:

<html>
<head><title><%= @greeting %></title></head>
<body>
<b><%= @greeting %></b>
</body>
</html>

Метод capture возвращает строку, сгенерированную блоком. Например:

@greeting # => "Welcome to my shiny new web page! The date and time is 2018-09-06 11:09:16 -0500"
content_for (name, content = nil, options = {}, &block) Показать исходный код
# File actionview/lib/action_view/helpers/capture_helper.rb, line 172
def content_for(name, content = nil, options = {}, &block)
  if content || block_given?
    if block_given?
      options = content if content
      content = capture(&block)
    end
    if content
      options[:flush] ? @view_flow.set(name, content) : @view_flow.append(name, content)
    end
    nil
  else
    @view_flow.get(name).presence
  end
end

Вызов content_for сохраняет блок разметки под идентификатором для последующего использования. Чтобы получить доступ к этому сохранённому содержимому из других шаблонов, модулей вспомогательных методов или макета, передайте идентификатор аргументом в content_for.

Примечание: yield по-прежнему можно использовать для получения сохранённого содержимого, но вызов yield не работает в модулях вспомогательных методов, тогда как content_for работает.

<% content_for :not_authorized do %>
  alert('You are not authorized to do that!')
<% end %>

Затем content_for :not_authorized можно использовать в любом месте шаблонов.

<%= content_for :not_authorized if current_user.nil? %>

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

<%= yield :not_authorized if current_user.nil? %>

Однако content_for также можно использовать в модулях вспомогательных методов.

module StorageHelper
  def stored_content
    content_for(:storage) || "Your storage is empty"
  end
end

Этот вспомогательный метод работает так же, как обычные вспомогательные методы.

<%= stored_content %>

Синтаксис yield также можно использовать вместе с существующим вызовом yield в макете. Например:

<%# This is the layout %>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <title>My Website</title>
  <%= yield :script %>
</head>
<body>
  <%= yield %>
</body>
</html>

Теперь создадим представление, в котором вызов content_for создаёт идентификатор script.

<%# This is our view %>
Please login!

<% content_for :script do %>
  <script>alert('You are not authorized to view this page!')</script>
<% end %>

Затем в другом представлении можно написать, например, следующее:

<%= link_to 'Logout', action: 'logout', remote: true %>

<% content_for :script do %>
  <%= javascript_include_tag :defaults %>
<% end %>

Это добавит на страницу теги script для набора файлов JavaScript по умолчанию; этот приём полезен, если эти скрипты используются лишь в нескольких представлениях.

Обратите внимание: content_for объединяет (по умолчанию) блоки, переданные для определённого идентификатора, в порядке их добавления. Например:

<% content_for :navigation do %>
  <li><%= link_to 'Home', action: 'index' %></li>
<% end %>

А в другом месте:

<% content_for :navigation do %>
  <li><%= link_to 'Login', action: 'login' %></li>
<% end %>

Затем в другом шаблоне или макете этот код выведет обе ссылки в том же порядке:

<ul><%= content_for :navigation %></ul>

Если параметр flush имеет значение true, content_for заменяет переданные ему блоки. Например:

<% content_for :navigation do %>
  <li><%= link_to 'Home', action: 'index' %></li>
<% end %>

<%# Add some other content, or use a different template: %>

<% content_for :navigation, flush: true do %>
  <li><%= link_to 'Login', action: 'login' %></li>
<% end %>

Затем в другом шаблоне или макете этот код выведет только последнюю ссылку:

<ul><%= content_for :navigation %></ul>

Наконец, простое содержимое можно передать в качестве параметра:

<% content_for :script, javascript_include_tag(:defaults) %>

ПРЕДУПРЕЖДЕНИЕ: content_for игнорируется при кэшировании. Поэтому не следует использовать его для элементов, которые будут кэшироваться во фрагментах.

content_for? (name) Показать исходный код
# File actionview/lib/action_view/helpers/capture_helper.rb, line 215
def content_for?(name)
  @view_flow.get(name).present?
end

content_for? проверяет, было ли уже сохранено какое-либо содержимое с помощью content_for.

Полезно для отображения разных частей макета в зависимости от содержимого представлений.

<%# This is the layout %>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <title>My Website</title>
  <%= yield :script %>
</head>
<body class="<%= content_for?(:right_col) ? 'two-column' : 'one-column' %>">
  <%= yield %>
  <%= yield :right_col %>
</body>
</html>
provide (name, content = nil, &block) Показать исходный код
# File actionview/lib/action_view/helpers/capture_helper.rb, line 194
def provide(name, content = nil, &block)
  content = capture(&block) if block_given?
  result = @view_flow.append!(name, content) if content
  result unless content
end

То же, что и content_for, но при использовании с потоковой передачей сразу отправляет содержимое в макет. Иными словами, если при отображении заданного шаблона нужно несколько раз добавить содержимое в один и тот же буфер, используйте content_for; в противном случае используйте provide, чтобы указать макету прекратить поиск дополнительного содержимого.

Подробнее см. в разделе ActionController::Streaming.

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

Spec-Zone.ru

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