Action View 捕获助手
CaptureHelper 提供方法来提取生成的标记,这些标记可用于模板或布局文件的其他部分。
它提供了一种通过 capture
将代码块捕获到变量中的方法,以及一种通过 content_for
将代码块捕获以在布局中使用的方法。
此外,它还提供了一种在使用流响应时的使用方法,通过 provide
。有关更多信息,请参阅 ActionController::Streaming
。
实例公共方法
capture(*args, &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(*args, &block) value = nil @output_buffer ||= ActionView::OutputBuffer.new buffer = @output_buffer.capture { value = yield(*args) } 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 %>
这将在页面上放置 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
在缓存中被忽略。因此,您不应该将其用于将被片段缓存的元素。
源代码:显示 | 在 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