更多内容请访问 rubyonrails.org:

Action View 助手

阅读本指南后,您将了解

  • 如何格式化日期、字符串和数字。
  • 如何处理文本和标签。
  • 如何链接到图像、视频、样式表等。
  • 如何在视图中处理 Atom 源和 JavaScript。
  • 如何缓存、捕获、调试和净化内容。

以下概述了 Action View 中可用的一些最常用的辅助方法。它是一个很好的起点,但也建议查阅完整的API 文档,因为它更详细地涵盖了所有辅助方法。

1. 格式化

1.1. 日期

这些辅助方法有助于将日期和/或时间元素显示为上下文的可读形式。

1.1.1. distance_of_time_in_words

报告两个 TimeDate 对象或作为秒数的整数之间的时间近似距离。如果您想要更详细的近似值,请将 include_seconds 设置为 true。

distance_of_time_in_words(Time.current, 15.seconds.from_now)
# => less than a minute
distance_of_time_in_words(Time.current, 15.seconds.from_now, include_seconds: true)
# => less than 20 seconds

我们使用 Time.current 而不是 Time.now,因为它根据 Rails 中设置的时区返回当前时间,而 Time.now 返回基于服务器时区的 Time 对象。

有关更多信息,请参阅distance_of_time_in_words API 文档

1.1.2. time_ago_in_words

报告 TimeDate 对象(或作为秒数的整数)与 Time.current 之间的时间近似距离。

time_ago_in_words(3.minutes.from_now) # => 3 minutes

有关更多信息,请参阅time_ago_in_words API 文档

1.2. 数字

一组用于将数字转换为格式化字符串的方法。提供了用于电话号码、货币、百分比、精度、位置表示法和文件大小的方法。

1.2.1. number_to_currency

将数字格式化为货币字符串(例如,$13.65)。

number_to_currency(1234567890.50) # => $1,234,567,890.50

有关更多信息,请参阅number_to_currency API 文档

1.2.2. number_to_human

美观打印(格式化和近似)数字,使其对用户更具可读性;适用于可能变得非常大的数字。

number_to_human(1234)    # => 1.23 Thousand
number_to_human(1234567) # => 1.23 Million

有关更多信息,请参阅number_to_human API 文档

1.2.3. number_to_human_size

将大小中的字节格式化为更易理解的表示形式;适用于向用户报告文件大小。

number_to_human_size(1234)    # => 1.21 KB
number_to_human_size(1234567) # => 1.18 MB

有关更多信息,请参阅number_to_human_size API 文档

1.2.4. number_to_percentage

将数字格式化为百分比字符串。

number_to_percentage(100, precision: 0) # => 100%

有关更多信息,请参阅number_to_percentage API 文档

1.2.5. number_to_phone

将数字格式化为电话号码(默认美国)。

number_to_phone(1235551234) # => 123-555-1234

有关更多信息,请参阅number_to_phone API 文档

1.2.6. number_with_delimiter

使用分隔符将数字按千位分组格式化。

number_with_delimiter(12345678) # => 12,345,678

有关更多信息,请参阅number_with_delimiter API 文档

1.2.7. number_with_precision

将数字格式化为指定的 precision 级别,默认为 3。

number_with_precision(111.2345)               # => 111.235
number_with_precision(111.2345, precision: 2) # => 111.23

有关更多信息,请参阅number_with_precision API 文档

1.3. 文本

一组用于过滤、格式化和转换字符串的方法。

1.3.1. excerpt

给定 textphraseexcerpt 搜索并提取 phrase 的第一次出现,以及由 radius 确定的请求周围文本。如果结果的开始/结束与文本的开始/结束不一致,则会在前面/后面添加省略标记。

excerpt("This is a very beautiful morning", "very", separator: " ", radius: 1)
# => ...a very beautiful...

excerpt("This is also an example", "an", radius: 8, omission: "<chop> ")
#=> <chop> is also an example

有关更多信息,请参阅excerpt API 文档

1.3.2. pluralize

根据数字的值返回单词的单数或复数形式。

pluralize(1, "person") # => 1 person
pluralize(2, "person") # => 2 people
pluralize(3, "person", plural: "users") # => 3 users

有关更多信息,请参阅pluralize API 文档

1.3.3. truncate

将给定 text 截断为给定 length。如果文本被截断,将在结果中添加一个省略标记,总长度不超过 length

truncate("Once upon a time in a world far far away")
# => "Once upon a time in a world..."

truncate("Once upon a time in a world far far away", length: 17)
# => "Once upon a ti..."

truncate("one-two-three-four-five", length: 20, separator: "-")
# => "one-two-three..."

truncate("And they found that many people were sleeping better.", length: 25, omission: "... (continued)")
# => "And they f... (continued)"

truncate("<p>Once upon a time in a world far far away</p>", escape: false)
# => "<p>Once upon a time in a wo..."

有关更多信息,请参阅truncate API 文档

1.3.4. word_wrap

将文本换行,每行长度不超过 line_width

word_wrap("Once upon a time", line_width: 8)
# => "Once\nupon a\ntime"

有关更多信息,请参阅word_wrap API 文档

2. 表单

与单独使用标准 HTML 元素相比,表单辅助方法简化了与模型的工作。它们提供了一系列根据您的模型生成表单的方法。有些方法对应于特定类型的输入,例如文本字段、密码字段、选择下拉列表等。当表单提交时,表单中的输入被分组到 params 对象中并发送回控制器。

您可以在Action View 表单辅助方法指南中了解有关表单辅助方法的更多信息。

一组用于构建依赖于路由子系统的链接和 URL 的方法。

3.1. button_to

生成一个提交到传递的 URL 的表单。该表单有一个提交按钮,其值为 name

<%= button_to "Sign in", sign_in_path %>

将输出以下 HTML

<form method="post" action="/sessions" class="button_to">
  <input type="submit" value="Sign in" />
</form>

有关更多信息,请参阅button_to API 文档

3.2. current_page?

如果当前请求 URL 与给定 options 匹配,则返回 true。

<% if current_page?(controller: 'profiles', action: 'show') %>
  <strong>Currently on the profile page</strong>
<% end %>

有关更多信息,请参阅current_page? API 文档

链接到在底层从 url_for 派生的 URL。它通常用于为 RESTful 资源创建链接,尤其是在将模型作为参数传递给 link_to 时。

link_to "Profile", @profile
# => <a href="/profiles/1">Profile</a>

link_to "Book", @book # given a composite primary key [:author_id, :id]
# => <a href="/books/2_1">Book</a>

link_to "Profiles", profiles_path
# => <a href="/profiles">Profiles</a>

link_to nil, "https://example.com"
# => <a href="https://example.com">https://example.com</a>

link_to "Articles", articles_path, id: "articles", class: "article__container"
# => <a href="/articles" class="article__container" id="articles">Articles</a>

如果您的链接目标不适合 name 参数,您可以使用块。

<%= link_to @profile do %>
  <strong><%= @profile.name %></strong> -- <span>Check it out!</span>
<% end %>

它将输出以下 HTML

<a href="/profiles/1">
  <strong>David</strong> -- <span>Check it out!</span>
</a>

有关更多信息,请参阅link_to API 文档

3.4. mail_to

生成一个指向指定电子邮件地址的 mailto 链接标签。您还可以指定链接文本、其他 HTML 选项以及是否编码电子邮件地址。

mail_to "john_doe@gmail.com"
# => <a href="mailto:john_doe@gmail.com">john_doe@gmail.com</a>

mail_to "me@john_doe.com", cc: "me@jane_doe.com",
        subject: "This is an example email"
# => <a href="mailto:"me@john_doe.com?cc=me@jane_doe.com&subject=This%20is%20an%20example%20email">"me@john_doe.com</a>

有关更多信息,请参阅mail_to API 文档

3.5. url_for

返回提供的 options 的 URL。

url_for @profile
# => /profiles/1

url_for [ @hotel, @booking, page: 2, line: 3 ]
# => /hotels/1/bookings/1?line=3&page=2

url_for @post # given a composite primary key [:blog_id, :id]
# => /posts/1_2

4. 净化

一组用于清除文本中不需要的 HTML 元素的方法。这些辅助方法对于帮助确保只呈现安全有效的 HTML/CSS 特别有用。它还可以通过在视图中呈现用户输入之前转义或删除潜在恶意内容来帮助防止 XSS 攻击。

此功能由 rails-html-sanitizer gem 在内部提供支持。

4.1. sanitize

sanitize 方法将 HTML 编码所有标签并去除所有未明确允许的属性。

sanitize @article.body

如果传递了 :attributes:tags 选项,则只允许提及的属性和标签,其他一律不允许。

sanitize @article.body, tags: %w(table tr td), attributes: %w(id class style)

要更改多次使用的默认值,例如,将表格标签添加到默认值

# config/application.rb
class Application < Rails::Application
  config.action_view.sanitized_allowed_tags = %w(table tr td)
end

有关更多信息,请参阅sanitize API 文档

4.2. sanitize_css

净化 CSS 代码块,特别是在 HTML 内容中遇到 style 属性时。sanitize_css 在处理用户生成的内容或包含 style 属性的动态内容时特别有用。

下面的 sanitize_css 方法将删除不允许的样式。

sanitize_css("background-color: red; color: white; font-size: 16px;")

有关更多信息,请参阅sanitize_css API 文档

从文本中去除所有链接标签,只保留链接文本。

strip_links("<a href='https://rubyonrails.cn'>Ruby on Rails</a>")
# => Ruby on Rails

strip_links("emails to <a href='mailto:me@email.com'>me@email.com</a>.")
# => emails to me@email.com.

strip_links("Blog: <a href='http://myblog.com/'>Visit</a>.")
# => Blog: Visit.

有关更多信息,请参阅strip_links API 文档

4.4. strip_tags

从 HTML 中去除所有 HTML 标签,包括注释和特殊字符。

strip_tags("Strip <i>these</i> tags!")
# => Strip these tags!

strip_tags("<b>Bold</b> no more! <a href='more.html'>See more</a>")
# => Bold no more! See more

strip_links('<<a href="https://example.org">malformed & link</a>')
# => &lt;malformed &amp; link

有关更多信息,请参阅strip_tags API 文档

5. 资产

一组用于生成将视图链接到图像、JavaScript 文件、样式表和提要等资产的 HTML 的方法。

默认情况下,Rails 将这些资产链接到公共文件夹中的当前主机上,但您可以通过在应用程序配置中设置 config.asset_host,通常在 config/environments/production.rb 中,来指示 Rails 从专用资产服务器链接到资产。

例如,假设您的资产主机是 assets.example.com

config.asset_host = "assets.example.com"

那么 image_tag 的相应 URL 将是

image_tag("rails.png")
# => <img src="//assets.example.com/images/rails.png" />

5.1. audio_tag

生成一个 HTML 音频标签,带有一个或多个源,可以是字符串源的单个标签,也可以是数组中多个源的嵌套源标签。sources 可以是完整路径、公共音频目录中的文件,或Active Storage 附件

audio_tag("sound")
# => <audio src="/audios/sound"></audio>

audio_tag("sound.wav", "sound.mid")
# => <audio><source src="/audios/sound.wav" /><source src="/audios/sound.mid" /></audio>

audio_tag("sound", controls: true)
# => <audio controls="controls" src="/audios/sound"></audio>

在内部,audio_tag 使用 AssetUrlHelpers 中的 audio_path 来构建音频路径。

有关更多信息,请参阅audio_tag API 文档

返回一个链接标签,浏览器和提要阅读器可以使用它来自动检测 RSS、Atom 或 JSON 提要。

auto_discovery_link_tag(:rss, "http://www.example.com/feed.rss", { title: "RSS Feed" })
# => <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="http://www.example.com/feed.rss" />

有关更多信息,请参阅auto_discovery_link_tag API 文档

返回一个由资产管道管理的 favicon 的链接标签。source 可以是完整路径或资产目录中存在的文件。

favicon_link_tag
# => <link href="/assets/favicon.ico" rel="icon" type="image/x-icon" />

有关更多信息,请参阅favicon_link_tag API 文档

5.4. image_tag

返回源的 HTML 图像标签。source 可以是完整路径或 app/assets/images 目录中存在的文件。

image_tag("icon.png")
# => <img src="/assets/icon.png" />

image_tag("icon.png", size: "16x10", alt: "Edit Article")
# => <img src="/assets/icon.png" width="16" height="10" alt="Edit Article" />

在内部,image_tag 使用 AssetUrlHelpers 中的 image_path 来构建图像路径。

有关更多信息,请参阅image_tag API 文档

5.5. javascript_include_tag

返回每个提供的源的 HTML script 标签。您可以传入 app/assets/javascripts 目录中存在的 JavaScript 文件的文件名(.js 扩展名可选)以包含到当前页面中,或者您可以传入相对于文档根目录的完整路径。

javascript_include_tag("common")
# => <script src="/assets/common.js"></script>

javascript_include_tag("common", async: true)
# => <script src="/assets/common.js" async="async"></script>

一些最常见的属性是 asyncdefer,其中 async 允许脚本并行加载并在尽快解析和评估,而 defer 则表示脚本应在文档解析后执行。

在内部,javascript_include_tag 使用 AssetUrlHelpers 中的 javascript_path 来构建脚本路径。

有关更多信息,请参阅javascript_include_tag API 文档

5.6. picture_tag

返回源的 HTML picture 标签。它支持传递字符串、数组或块。

picture_tag("icon.webp", "icon.png")

这会生成以下 HTML

<picture>
  <source srcset="/assets/icon.webp" type="image/webp" />
  <source srcset="/assets/icon.png" type="image/png" />
  <img src="/assets/icon.png" />
</picture>

有关更多信息,请参阅picture_tag API 文档

返回一个链接标签,浏览器可以使用它来预加载源。源可以是资产管道管理的资源的路径、完整路径或 URI。

preload_link_tag("application.css")
# => <link rel="preload" href="/assets/application.css" as="style" type="text/css" />

有关更多信息,请参阅preload_link_tag API 文档

返回指定为参数的源的样式表链接标签。如果您未指定扩展名,将自动添加 .css

stylesheet_link_tag("application")
# => <link href="/assets/application.css" rel="stylesheet" />

stylesheet_link_tag("application", media: "all")
# => <link href="/assets/application.css" media="all" rel="stylesheet" />

media 用于指定链接的媒体类型。最常见的媒体类型是 allscreenprintspeech

在内部,stylesheet_link_tag 使用 AssetUrlHelpers 中的 stylesheet_path 来构建样式表路径。

有关更多信息,请参阅stylesheet_link_tag API 文档

5.9. video_tag

生成一个带有源的 HTML 视频标签,可以是字符串源的单个标签,也可以是数组中多个源的嵌套源标签。sources 可以是完整路径、公共视频目录中的文件,或 Active Storage 附件。

video_tag("trailer")
# => <video src="/videos/trailer"></video>

video_tag(["trailer.ogg", "trailer.flv"])
# => <video><source src="/videos/trailer.ogg" /><source src="/videos/trailer.flv" /></video>

video_tag("trailer", controls: true)
# => <video controls="controls" src="/videos/trailer"></video>

在内部,video_tag 使用 AssetUrlHelpers 中的 video_path 来构建视频路径。

有关更多信息,请参阅video_tag API 文档

6. JavaScript

一组用于在视图中处理 JavaScript 的方法。

6.1. escape_javascript

转义 JavaScript 片段中的回车符、单引号和双引号。您可以使用此方法来处理文本字符串,并确保它在浏览器尝试解析时不会包含任何无效字符。

例如,如果您有一个带有包含双引号的问候语的部分视图,您可以转义该问候语以在 JavaScript 警告中使用。

<%# app/views/users/greeting.html.erb %>
My name is <%= current_user.name %>, and I'm here to say "Welcome to our website!"
<script>
  var greeting = "<%= escape_javascript render('users/greeting') %>";
  alert(`Hello, ${greeting}`);
</script>

这将正确转义引号并在警报框中显示问候语。

有关更多信息,请参阅escape_javascript API 文档

6.2. javascript_tag

返回一个包裹所提供代码的 JavaScript 标签。您可以传递一个选项哈希来控制 <script> 标签的行为。

javascript_tag("alert('All is good')", type: "application/javascript")
<script type="application/javascript">
//<![CDATA[
alert('All is good')
//]]>
</script>

除了将内容作为参数传递,您还可以使用块。

<%= javascript_tag type: "application/javascript" do %>
  alert("Welcome to my app!")
<% end %>

有关更多信息,请参阅javascript_tag API 文档

7. 替代标签

一组用于以编程方式生成 HTML 标签的方法。

7.1. tag

生成具有给定 nameoptions 的独立 HTML 标签。

每个标签都可以通过以下方式构建

tag.some_tag_name(optional content, options)

其中标签名称可以是例如 brdivsectionarticle 或任何标签。

例如,以下是一些常见用法

tag.h1 "All titles fit to print"
# => <h1>All titles fit to print</h1>

tag.div "Hello, world!"
# => <div>Hello, world!</div>

此外,您可以传递选项以向生成的标签添加属性。

tag.section class: %w( kitties puppies )
# => <section class="kitties puppies"></section>

此外,HTML data-* 属性可以通过 data 选项传递给 tag 辅助方法,其中包含子属性的键值对哈希。然后,子属性转换为 data-* 属性,这些属性被破折号连接,以便与 JavaScript 很好地协同工作。

tag.div data: { user_id: 123 }
# => <div data-user-id="123"></div>

有关更多信息,请参阅tag API 文档

7.2. token_list

返回由提供的参数构建的 token 字符串。此方法也别名为 class_names

token_list("cats", "dogs")
# => "cats dogs"

token_list(nil, false, 123, "", "foo", { bar: true })
# => "123 foo bar"

mobile, alignment = true, "center"
token_list("flex items-#{alignment}", "flex-col": mobile)
# => "flex items-center flex-col"
class_names("flex items-#{alignment}", "flex-col": mobile) # using the alias
# => "flex items-center flex-col"

8. 捕获块

一组方法,允许您提取生成的标记,这些标记可用于模板或布局文件的其他部分。

它提供了一种通过 capture 将块捕获到变量中的方法,以及一种通过 content_for 捕获标记块以在布局中使用的S方法。

8.1. capture

capture 方法允许您将模板的一部分提取到变量中。

<% @greeting = capture do %>
  <p>Welcome! The date and time is <%= Time.current %></p>
<% end %>

然后,您可以在模板、布局或辅助方法中的任何位置使用此变量。

<html>
  <head>
    <title>Welcome!</title>
  </head>
  <body>
    <%= @greeting %>
  </body>
</html>

捕获的返回值是块生成的字符串。

@greeting
# => "Welcome! The date and time is 2018-09-06 11:09:16 -0500"

有关更多信息,请参阅capture API 文档

8.2. content_for

调用 content_for 会将标记块存储在标识符中以供以后使用。您可以通过将标识符作为参数传递给 yield,在其他模板、辅助模块或布局中对存储的内容进行后续调用。

一个常见的用例是在 content_for 块中设置页面的标题。

您在特殊页面的视图中定义一个 content_for 块,然后将其 yield 到布局中。对于其他未利用 content_for 块的页面,它仍然是空的,导致没有任何内容被 yield。

<%# app/views/users/special_page.html.erb %>
<% content_for(:html_title) { "Special Page Title" } %>
<%# app/views/layouts/application.html.erb %>
<html>
  <head>
    <title><%= content_for?(:html_title) ? yield(:html_title) : "Default Title" %></title>
  </head>
</html>

您会注意到在上面的示例中,我们使用 content_for? 谓词方法有条件地呈现标题。此方法检查是否已使用 content_for 捕获任何内容,使您能够根据视图中的内容调整布局的部分。

此外,您可以在辅助模块中使用 content_for

# app/helpers/title_helper.rb
module TitleHelper
  def html_title
    content_for(:html_title) || "Default Title"
  end
end

现在,您可以在布局中调用 html_title 来检索存储在 content_for 块中的内容。如果正在渲染的页面(例如 special_page)上设置了 content_for 块,它将显示标题。否则,它将显示默认文本“Default Title”。

content_for 在缓存中被忽略。因此,您不应将其用于将进行片段缓存的元素。

您可能会想 capturecontent_for 有什么区别?

capture 用于将标记块捕获到变量中,而 content_for 用于将标记块存储在标识符中以供以后使用。在内部,content_for 实际上调用了 capture。然而,关键区别在于它们在多次调用时的行为。

content_for 可以重复调用,它会按照提供的顺序连接它为特定标识符接收的块。每次后续调用只会增加已存储的内容。相比之下,capture 只返回块的内容,而不跟踪任何以前的调用。

有关更多信息,请参阅content_for API 文档

9. 性能

9.1. benchmark

benchmark 块包裹在昂贵的操作或可能的瓶颈周围,以获取操作的时间读数。

<% benchmark "Process data files" do %>
  <%= expensive_files_operation %>
<% end %>

这会在日志中添加类似 Process data files (0.34523) 的内容,然后您可以使用它来比较优化代码时的时间。

此辅助方法是 Active Support 的一部分,它也适用于控制器、辅助方法、模型等。

有关更多信息,请参阅benchmark API 文档

9.2. cache

您可以缓存视图的片段而不是整个操作或页面。此技术对于缓存菜单、新闻主题列表、静态 HTML 片段等片段非常有用。它允许将视图逻辑的片段包裹在缓存块中,并在下次请求时从缓存存储中提供。

cache 方法接受一个包含您希望缓存内容的块。

例如,您可以通过将其包裹在 cache 块中来缓存应用程序布局的页脚。

<% cache do %>
  <%= render "application/footer" %>
<% end %>

您还可以基于模型实例进行缓存,例如,您可以通过将 article 对象传递给 cache 方法来缓存页面上的每篇文章。这将单独缓存每篇文章。

<% @articles.each do |article| %>
  <% cache article do %>
    <%= render article %>
  <% end %>
<% end %>

当您的应用程序收到对该页面的第一个请求时,Rails 将写入一个新的缓存条目,其中包含唯一的键。键看起来像这样

views/articles/index:bea67108094918eeba32cd4a6f786301/articles/1

有关更多信息,请参阅Fragment Cachingcache API 文档

10. 杂项

10.1. atom_feed

Atom Feeds 是基于 XML 的文件格式,用于内容联合,用户可以在提要阅读器中浏览内容,或搜索引擎可以帮助发现有关您网站的其他信息。

此辅助方法使构建 Atom 提要变得容易,并且主要用于 Builder 模板中创建 XML。这是一个完整的用法示例

# config/routes.rb
resources :articles
# app/controllers/articles_controller.rb
def index
  @articles = Article.all

  respond_to do |format|
    format.html
    format.atom
  end
end
# app/views/articles/index.atom.builder
atom_feed do |feed|
  feed.title("Articles Index")
  feed.updated(@articles.first.created_at)

  @articles.each do |article|
    feed.entry(article) do |entry|
      entry.title(article.title)
      entry.content(article.body, type: "html")

      entry.author do |author|
        author.name(article.author_name)
      end
    end
  end
end

有关更多信息,请参阅atom_feed API 文档

10.2. debug

返回包裹在 pre 标签中的对象的 YAML 表示。这创建了一种非常可读的方式来检查对象。

my_hash = { "first" => 1, "second" => "two", "third" => [1, 2, 3] }
debug(my_hash)
<pre class="debug_dump">---
first: 1
second: two
third:
- 1
- 2
- 3
</pre>

有关更多信息,请参阅debug API 文档



回到顶部