модуль ActionView::Helpers::CaptureHelper
CaptureHelper предоставляет методы для извлечения сгенерированного разметки, которое можно использовать в других частях шаблона или файла макета.
Он предоставляет метод для захвата блоков в переменные с помощью capture и способ захвата блока разметки для использования в макете с помощью content_for.
Публичные методы экземпляра
# File actionview/lib/action_view/helpers/capture_helper.rb, line 36
def capture(*args)
value = nil
buffer = with_output_buffer { value = yield(*args) }
if string = buffer.presence || value and string.is_a?(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>
# File actionview/lib/action_view/helpers/capture_helper.rb, line 148
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 other 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 игнорируется в кэшах. Поэтому вы не должны использовать его для элементов, которые будут фрагментарно кэшированы.
# File actionview/lib/action_view/helpers/capture_helper.rb, line 188 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>
# File actionview/lib/action_view/helpers/capture_helper.rb, line 168 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.