更多内容请访问 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,因为 Time.current 返回基于 Rails 中设置的时区的时间,而 Time.now 返回基于服务器时区的时间对象。

有关更多信息,请参阅 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>

如果您的链接目标无法放入名称参数中,可以使用块。

<%= 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 "[email protected]"
# => <a href="mailto:[email protected]">[email protected]</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 属性时。当处理用户生成的内容或包含 style 属性的动态内容时,sanitize_css特别有用。

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

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

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

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

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

strip_links("emails to <a href='mailto:[email protected]'>[email protected]</a>.")
# => emails to [email protected].

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 资产

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

默认情况下,Rails 将这些资产链接到公共文件夹中的当前主机,但是您可以通过在应用程序配置(通常在config/environments/production.rb中)中设置config.asset_host来指示 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 文档

返回一个指向由资产管道管理的收藏夹图标的链接标签。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 脚本标签。您可以传入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 代码段中的单引号和双引号。您将使用此方法来获取一段文本,并确保浏览器尝试解析它时它不包含任何无效字符。

例如,如果您有一个包含包含双引号的 greetings 的部分,您可以转义 greetings 以在 JavaScript alert 中使用。

<%# 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>

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

有关更多信息,请参阅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

返回从提供的参数构建的令牌字符串。此方法也称为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捕获标记块以在布局中使用的方法。

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>

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

@greeting
# => "Welcome to my shiny new web page! 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 块,它将保持为空,导致不会产生任何内容。

<%# 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 块中的内容。如果在正在渲染的页面上设置了 content_for 块(例如在 special_page 的情况下),它将显示标题。否则,它将显示默认文本“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

有关更多信息,请参阅 片段缓存cache API 文档

10 杂项

10.1 atom_feed

Atom Feed 是基于 XML 的文件格式,用于联合内容,用户可以使用 Feed 阅读器浏览内容,搜索引擎可以使用它来帮助发现有关您网站的更多信息。

此辅助方法使构建 Atom Feed 变得容易,主要用于 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 文档



返回顶部