Action View Capture Helpers¶ ↑
CaptureHelper 提供了方法,让您可以提取生成的标记,这些标记可以在模板或其他布局文件的其他部分中使用。
它提供了一个方法,通过 capture 将块捕获到变量中,并通过 content_for 捕获标记块以在布局中使用。
此外,当使用流式响应时,它还提供了一个方法 provide。有关更多信息,请参阅 ActionController::Streaming。
实例公共方法
capture(*, **, &block) 链接
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"
来源: 显示 | 在 GitHub 上
# 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
content_for(name, content = nil, options = {}, &block) 链接
调用 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 %>
这将会在页面上放置用于默认 JavaScript 文件集的 script 标签;如果您只会在少数视图中使用这些脚本,这种技术非常有用。
请注意,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 在缓存时会被忽略。因此,您不应将其用于将被片段缓存的元素。
来源: 显示 | 在 GitHub 上
# 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?(name) 链接
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>
来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/capture_helper.rb, line 215 def content_for?(name) @view_flow.get(name).present? end
provide(name, content = nil, &block) 链接
与 content_for 相同,但在与流式传输一起使用时,它会直接刷新回布局。换句话说,如果您想在渲染给定模板时多次连接到同一个缓冲区,您应该使用 content_for;否则,请使用 provide 来告诉布局停止查找更多内容。
有关更多信息,请参阅 ActionController::Streaming。
来源: 显示 | 在 GitHub 上
# 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