Action View 基础
Action View 模板可以以多种方式编写。如果模板文件具有.erb
扩展名,则它使用erubi模板系统,该系统可以将 Ruby 嵌入到 HTML 文档中。如果模板文件具有.builder
扩展名,则使用 Jim Weirich 的 Builder::XmlMarkup 库。
ERB
您可以通过使用诸如<% %>
、<% -%>
和<%= %>
之类的嵌入来触发ERB
。当您需要输出时,使用<%= %>
标签集。考虑以下名称循环
<b>Names of all the people</b>
<% @people.each do |person| %>
Name: <%= person.name %><br/>
<% end %>
循环是在常规嵌入标签<% %>
中设置的,名称使用输出嵌入标签<%= %>
写入。请注意,这不仅仅是使用建议。常规输出函数(如 print 或 puts)不适用于ERB
模板。所以这样就错了
<%# WRONG %>
Hi, Mr. <% puts "Frodo" %>
如果您绝对必须从函数内部写入,请使用concat
。
在一行仅包含空格(标签除外)的情况下,<% %>
会抑制前导和尾随空格,包括尾随换行符。<% %>
和<%- -%>
相同。但是请注意,<%= %>
和<%= -%>
不同:只有后者会删除尾随空格。
使用子模板
使用子模板可以避免繁琐的复制,并在共享模板中提取常见的显示结构。经典的例子是使用页眉和页脚(即使 Action Pack 的方法是使用布局
)
<%= render "application/header" %>
Something really specific and terrific
<%= render "application/footer" %>
如您所见,我们对渲染方法使用输出嵌入。渲染调用本身只会返回一个字符串,其中包含渲染结果。输出嵌入将其写入当前模板。
但是您不必局限于静态包含。模板可以通过使用使用常规嵌入标签定义的实例变量来相互共享变量。就像这样
<% @page_title = "A Wonderful Hello" %>
<%= render "application/header" %>
现在页眉可以获取@page_title
变量并将其用于输出标题标签
<title><%= @page_title %></title>
将局部变量传递给子模板
您可以通过使用一个哈希表(将变量名作为键,对象作为值)将局部变量传递给子模板
<%= render "application/header", { headline: "Welcome", person: person } %>
现在可以在application/header
中使用以下方式访问它们
Headline: <%= headline %>
First name: <%= person.first_name %>
传递给子模板的局部变量可以使用local_assigns
哈希表作为哈希表访问。这样您就可以像这样访问变量
Headline: <%= local_assigns[:headline] %>
这在您不确定局部变量是否已分配的情况下很有用。或者,您也可以使用defined? headline
先检查变量是否已分配,然后再使用它。
默认情况下,模板将接受任何locals
作为关键字参数。要限制模板接受的locals
,请添加locals:
魔法注释
<%# locals: (headline:) %>
Headline: <%= headline %>
在局部变量是可选的情况下,使用默认值声明关键字参数
<%# locals: (headline: nil) %>
<% unless headline.nil? %>
Headline: <%= headline %>
<% end %>
在指南中阅读有关严格本地变量的更多信息,请访问Action View 概述。
模板
缓存
默认情况下,Rails 会将每个模板编译成一个方法以进行渲染。当您修改模板时,Rails 会检查文件的修改时间并在开发模式下重新编译它。
构建器
构建器模板是ERB
的更具程序性的替代方案。它们在生成 XML 内容时特别有用。一个名为xml
的 XmlMarkup 对象会自动提供给具有.builder
扩展名的模板。
以下是一些基本示例
xml.em("emphasized") # => <em>emphasized</em>
xml.em { xml.b("emph & bold") } # => <em><b>emph & bold</b></em>
xml.a("A Link", "href" => "http://onestepback.org") # => <a href="http://onestepback.org">A Link</a>
xml.target("name" => "compile", "option" => "fast") # => <target option="fast" name="compile"\>
# NOTE: order of attributes is not specified.
任何带有块的方法都将被视为具有块中嵌套标记的 XML 标记标签。例如,以下内容
xml.div do
xml.h1(@person.name)
xml.p(@person.bio)
end
将产生类似以下内容
<div>
<h1>David Heinemeier Hansson</h1>
<p>A product of Danish Design during the Winter of '79...</p>
</div>
以下是在 Basecamp 上实际使用的完整 RSS 示例
xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/") do
xml.channel do
xml.title(@feed_title)
xml.link(@url)
xml.description "Basecamp: Recent items"
xml.language "en-us"
xml.ttl "40"
@recent_items.each do |item|
xml.item do
xml.title(item_title(item))
xml.description(item_description(item)) if item_description(item)
xml.pubDate(item_pubDate(item))
xml.guid(@person.firm.account.url + @recent_items.url(item))
xml.link(@person.firm.account.url + @recent_items.url(item))
xml.tag!("dc:creator", item.author_name) if item_has_creator?(item)
end
end
end
end
有关构建器的更多信息,请参阅源代码。
- #
- C
- I
属性
[R] | lookup_context | |
[R] | view_renderer |
类公共方法
cache_template_loading() 链接
来源:显示 | 在 GitHub 上
# File actionview/lib/action_view/base.rb, line 187 def cache_template_loading ActionView::Resolver.caching? end
cache_template_loading=(value) 链接
来源:显示 | 在 GitHub 上
# File actionview/lib/action_view/base.rb, line 191 def cache_template_loading=(value) ActionView::Resolver.caching = value end
inspect() 链接
来源:显示 | 在 GitHub 上
# File actionview/lib/action_view/base.rb, line 207 def inspect "#<ActionView::Base:#{'%#016x' % (object_id << 1)}>" end
实例公共方法
_run(method, template, locals, buffer, add_to_stack: true, has_strict_locals: false, &block) 链接
来源:显示 | 在 GitHub 上
# File actionview/lib/action_view/base.rb, line 261 def _run(method, template, locals, buffer, add_to_stack: true, has_strict_locals: false, &block) _old_output_buffer, _old_virtual_path, _old_template = @output_buffer, @virtual_path, @current_template @current_template = template if add_to_stack @output_buffer = buffer if has_strict_locals begin public_send(method, locals, buffer, **locals, &block) rescue ArgumentError => argument_error raise( ArgumentError, argument_error. message. gsub("unknown keyword:", "unknown local:"). gsub("missing keyword:", "missing local:"). gsub("no keywords accepted", "no locals accepted"). concat(" for #{@current_template.short_identifier}") ) end else public_send(method, locals, buffer, &block) end ensure @output_buffer, @virtual_path, @current_template = _old_output_buffer, _old_virtual_path, _old_template end
compiled_method_container() 链接
来源:显示 | 在 GitHub 上
# File actionview/lib/action_view/base.rb, line 287 def compiled_method_container raise NotImplementedError, <<~msg.squish Subclasses of ActionView::Base must implement `compiled_method_container` or use the class method `with_empty_template_cache` for constructing an ActionView::Base subclass that has an empty cache. msg end
in_rendering_context(options) 链接
来源:显示 | 在 GitHub 上
# File actionview/lib/action_view/base.rb, line 295 def in_rendering_context(options) old_view_renderer = @view_renderer old_lookup_context = @lookup_context if !lookup_context.html_fallback_for_js && options[:formats] formats = Array(options[:formats]) if formats == [:js] formats << :html end @lookup_context = lookup_context.with_prepended_formats(formats) @view_renderer = ActionView::Renderer.new @lookup_context end yield @view_renderer ensure @view_renderer = old_view_renderer @lookup_context = old_lookup_context end