Spec-Zone.ru › Ruby on Rails 5.1

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

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

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

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

capture(*args) { |*args| ... } Показать исходный код
# File actionview/lib/action_view/helpers/capture_helper.rb, line 37
def capture(*args)
  value = nil
  buffer = with_output_buffer { value = yield(*args) }
  if (string = buffer.presence || value) && string.is_a?(String)
    ERB::Util.html_escape string
  end
end

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

Метод 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>
content_for(name, content = nil, options = {}, &block) Показать исходный код
# File actionview/lib/action_view/helpers/capture_helper.rb, line 149
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 %>

And in another place:

 <% 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 189
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 169
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, чтобы сообщить макету прекратить поиск большего содержимого.

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

Spec-Zone.ru

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