1 升级到 Rails 5.1
如果升级现有应用,在继续之前,最好确保有足够的测试覆盖度。如果尚未升级到 Rails 5.0,应该先升级到 5.0 版,确保应用能正常运行之后,再尝试升级到 Rails 5.1。升级时的注意事项参见 从 Rails 5.0 升级到 5.1。
2 主要功能
2.1 支持 Yarn
Rails 5.1 支持使用 Yarn 管理通过 NPM 安装的 JavaScript 依赖。这样便于使用 NPM 中的 React、VueJS 等库。对 Yarn 的支持集成在 Asset Pipeline 中,因此所有依赖都能顺利在 Rails 5.1 应用中使用。
2.2 Webpack 支持(可选)
Rails 应用使用新开发的 Webpacker gem 可以轻易集成 JavaScript 静态资源打包工具 Webpack。新建应用时指定 --webpack
参数可启用对 Webpack 的集成。
这与 Asset Pipeline 完全兼容,你可以继续使用 Asset Pipeline 管理图像、字体、音频等静态资源。甚至还可以使用 Asset Pipeline 管理部分 JavaScript 代码,使用 Webpack 管理其他代码。这些都由默认启用的 Yarn 管理。
2.3 jQuery 不再是默认的依赖
Rails 之前的版本默认需要 jQuery,因为要支持 data-remote
和 data-confirm
等功能,以及 Rails 提供的非侵入式 JavaScript。现在 jQuery 不再需要了,因为 UJS 使用纯 JavaScript 重写了。这个脚本现在通过 Action View 提供,名为 rails-ujs
。
如果需要,可以继续使用 jQuery,但它不再是默认的依赖了。
2.4 系统测试
Rails 5.1 内建对 Capybara 测试的支持,不过对外称为系统测试。你无需再担心配置 Capybara 和数据库清理策略。Rails 5.1 对这类测试做了包装,可以在 Chrome 运行相关测试,而且失败时还能截图。
2.5 机密信息加密
受 sekrets gem 启发,Rails 现在以一种安全的方式管理应用中的机密信息。
运行 bin/rails secrets:setup
,创建一个加密的机密信息文件。这个命令还会生成一个主密钥,必须把它放在仓库外部。机密信息已经加密,可以放心检入版本控制系统。
在生产环境中,Rails 会使用 RAILS_MASTER_KEY
环境变量或密钥文件中的密钥解密机密信息。
2.6 参数化邮件程序
允许为一个邮件程序类中的所有方法指定通用的参数,方便共享实例变量、首部和其他数据。
class InvitationsMailer < ApplicationMailer before_action { @inviter, @invitee = params[:inviter], params[:invitee] } before_action { @account = params[:inviter].account } def account_invitation mail subject: "#{@inviter.name} invited you to their Basecamp (#{@account.name})" end end InvitationsMailer.with(inviter: person_a, invitee: person_b) .account_invitation.deliver_later
2.7 direct 路由和 resolve 路由
Rails 5.1 为路由 DSL 增加了两个新方法:resolve
和 direct
。前者用于定制模型的多态映射。
resource :basket resolve("Basket") { [:basket] }
<%= form_for @basket do |form| %> <!-- basket form --> <% end %>
此时生成的 URL 是单数形式的 /basket
,而不是往常的 /baskets/:id
。
direct
用于创建自定义的 URL 辅助方法。
direct(:homepage) { "http://www.rubyonrails.org" }
>> homepage_url => "http://www.rubyonrails.org"
块的返回值必须能用作 url_for
方法的参数。因此,可以传入有效的 URL 字符串、散列、数组、Active Model 实例或 Active Model 类。
direct :commentable do |model| [ model, anchor: model.dom_id ] end direct :main do { controller: 'pages', action: 'index', subdomain: 'www' } end
2.8 form_for
和 form_tag
统一为 form_with
在 Rails 5.1 之前,处理 HTML 表单有两个接口:针对模型实例的 form_for
和针对自定义 URL 的 form_tag
。
Rails 5.1 把这两个接口统一成 form_with
了,可以根据 URL、作用域或模型生成表单标签。
只使用 URL:
<%= form_with url: posts_path do |form| %> <%= form.text_field :title %> <% end %> <%# 生成的表单为 %> <form action="/posts" method="post" data-remote="true"> <input type="text" name="title"> </form>
指定作用域,添加到输入字段的名称前:
<%= form_with scope: :post, url: posts_path do |form| %> <%= form.text_field :title %> <% end %> <%# 生成的表单为 %> <form action="/posts" method="post" data-remote="true"> <input type="text" name="post[title]"> </form>
使用模型,从中推知 URL 和作用域:
<%= form_with model: Post.new do |form| %> <%= form.text_field :title %> <% end %> <%# 生成的表单为 %> <form action="/posts" method="post" data-remote="true"> <input type="text" name="post[title]"> </form>
现有模型的更新表单填有字段的值:
<%= form_with model: Post.first do |form| %> <%= form.text_field :title %> <% end %> <%# 生成的表单为 %> <form action="/posts/1" method="post" data-remote="true"> <input type="hidden" name="_method" value="patch"> <input type="text" name="post[title]" value="<the title of the post>"> </form>
3 不兼容的功能
下述变动需要立即采取行动。
3.1 使用多个连接的事务型测试
事务型测试现在把所有 Active Record 连接包装在数据库事务中。
如果测试派生额外的线程,而且线程获得了数据库连接,这些连接现在使用特殊的方式处理。
这些线程将共享一个连接,放在事务中。这样能确保所有线程看到的数据库状态是一样的,忽略最外层的事务。以前,额外的连接无法查看固件记录。
线程进入嵌套的事务时,为了维护隔离性,它会临时获得连接的专用权。
如果你的测试目前要在派生的线程中获得不在事务中的单独连接,需要直接管理连接。
如果测试派生线程,而线程与显式数据库事务交互,这一变化可能导致死锁。
若想避免这个新行为的影响,简单的方法是在受影响的测试用例上禁用事务型测试。
4 Railties
变化详情参见 Changelog。
4.1 删除
- 删除弃用的
config.static_cache_control
。(提交) - 删除弃用的
config.serve_static_files
。(提交) - 删除弃用的
rails/rack/debugger
。(提交) - 删除弃用的任务:
rails:update
,rails:template
,rails:template:copy
,rails:update:configs
和rails:update:bin
。(提交) - 删除
routes
任务弃用的CONTROLLER
环境变量。(提交) - 删除
rails new
命令的-j
(--javascript
)选项。(拉取请求)
4.2 重要变化
- 在
config/secrets.yml
中添加一部分,供所有环境使用。(提交) -
config/secrets.yml
文件中的所有键现在都通过符号加载。(拉取请求) - 从默认栈中删除 jquery-rails。Action View 提供的 rails-ujs 现在是默认的 UJS 适配器。(拉取请求)
- 为新应用添加 Yarn 支持,创建 yarn binstub 和 package.json。(拉取请求)
- 通过
--webpack
选项为新应用添加 Webpack 支持,相关功能由 rails/webpacker gem 提供。(拉取请求) - 生成新应用时,如果没提供
--skip-git
选项,初始化 Git 仓库。(拉取请求) - 在
config/secrets.yml.enc
文件中保存加密的机密信息。(拉取请求) - 在
rails initializers
中显示 railtie 类名。(拉取请求)
5 Action Cable
变化详情参见 Changelog。
5.1 重要变化
- 允许在
cable.yml
中为 Redis 和事件型 Redis 适配器提供channel_prefix
,以防多个应用使用同一个 Redis 服务器时名称有冲突。(拉取请求) - 添加
ActiveSupport::Notifications
钩子,用于广播数据。(拉取请求)
6 Action Pack
变化详情参见 Changelog。
6.1 删除
-
ActionDispatch::IntegrationTest
和ActionController::TestCase
类的#process
、#get
、#post
、#patch
、#put
、#delete
和#head
等方法不再允许使用非关键字参数。(提交,提交) - 删除弃用的
ActionDispatch::Callbacks.to_prepare
和ActionDispatch::Callbacks.to_cleanup
。(提交) - 删除弃用的与控制器过滤器有关的方法。(提交)
6.2 弃用
- 弃用
config.action_controller.raise_on_unfiltered_parameters
。在 Rails 5.1 中没有任何效果。(提交)
6.3 重要变化
7 Action View
变化详情参见 Changelog。
7.1 删除
- 删除
ActionView::Template::Error
中弃用的#original_exception
方法。(提交) - 删除
strip_tags
方法不恰当的encode_special_chars
选项。(拉取请求)
7.2 弃用
- 弃用 ERB 处理程序 Erubis,换成 Erubi。(拉取请求)
7.3 重要变化
- 原始模板处理程序(Rails 5 默认的模板处理程序)现在输出对 HTML 安全的字符串。(提交)
- 修改
datetime_field
和datetime_field_tag
,让它们生成datetime-local
字段。(拉取请求) - 新增 Builder 风格的 HTML 标签句法(
tag.div
、tag.br
,等等)。(拉取请求) - 添加
form_with
,统一form_tag
和form_for
。(拉取请求) - 为
current_page?
方法添加check_parameters
选项。(拉取请求)
8 Action Mailer
变化详情参见 Changelog。
8.1 重要变化
- 有附件而且在行间设定正文时,允许自定义内容类型。(拉取请求)
- 允许把 lambda 传给
default
方法。(提交) - 支持参数化邮件程序,在动作之间共享前置过滤器和默认值。(提交)
- 把传给邮件程序动作的参数传给
process.action_mailer
时间,放在args
键名下。(拉取请求)
9 Active Record
变化详情参见 Changelog。
9.1 删除
- 不再允许同时为
ActiveRecord::QueryMethods#select
传入参数和块。(提交) - 删除弃用的 i18n 作用域
activerecord.errors.messages.restrict_dependent_destroy.one
和activerecord.errors.messages.restrict_dependent_destroy.many
。(提交) - 删除单个和集合关系读值方法中弃用的
force_reload
参数。(提交) - 不再支持把一列传给
#quote
。(提交) - 删除
#tables
方法弃用的name
参数。(提交) -
#tables
和#table_exists?
不再返回表和视图,而只返回表。(提交) - 删除
ActiveRecord::StatementInvalid#initialize
和ActiveRecord::StatementInvalid#original_exception
弃用的original_exception
参数。(提交) - 不再支持在查询中使用类。(提交)
- 不再支持在 LIMIT 子句中使用逗号。(提交)
- 删除
#destroy_all
弃用的conditions
参数。(提交) - 删除
#delete_all
弃用的conditions
参数。(提交) - 删除弃用的
#load_schema_for
方法,换成#load_schema
。(提交) - 删除弃用的
#raise_in_transactional_callbacks
配置。(提交) - 删除弃用的
#use_transactional_fixtures
配置。(提交)
9.2 弃用
- 弃用
error_on_ignored_order_or_limit
旗标,改用error_on_ignored_order
。(提交) - 弃用
sanitize_conditions
,改用sanitize_sql
。(拉取请求) - 弃用连接适配器的
supports_migrations?
方法。(拉取请求) - 弃用
Migrator.schema_migrations_table_name
,改用SchemaMigration.table_name
。(拉取请求) - 加引号和做类型转换时不再调用
#quoted_id
。(拉取请求) -
#index_name_exists?
方法不再接受default
参数。(拉取请求)
9.3 重要变化
- 主键的默认类型改为 BIGINT。(拉取请求)
- 支持 MySQL 5.7.5+ 和 MariaDB 5.2.0+ 的虚拟(生成的)列。(提交)
- 支持在批量处理时限制记录数量。(提交)
- 事务型测试现在把所有 Active Record 连接包装在数据库事务中。(拉取请求)
- 默认跳过
mysqldump
命令输出的注释。(拉取请求) - 把块传给
ActiveRecord::Relation#count
时,使用 Ruby 的Enumerable#count
计算记录数量,而不是悄无声息地忽略块。(拉取请求) - 把
"-v ON_ERROR_STOP=1"
旗标传给psql
命令,不静默 SQL 错误。(拉取请求) - 添加
ActiveRecord::Base.connection_pool.stat
。(拉取请求) - 如果直接继承
ActiveRecord::Migration
,抛出错误。应该指定迁移针对的 Rails 版本。(提交) - 通过
through
建立的关联,如果反射名称有歧义,抛出错误。(提交)
10 Active Model
变化详情参见 Changelog。
10.1 删除
10.2 重要变化
- 赋值给模型属性的字符串现在能正确冻结了。(拉取请求)
11 Active Job
变化详情参见 Changelog。
11.1 删除
11.2 重要变化
- 增加通过
ActiveJob::Base.retry_on
和ActiveJob::Base.discard_on
实现的声明式异常处理。(拉取请求) - 把作业实例传入块,这样在尝试失败后可以访问
job.arguments
等信息。(提交)
12 Active Support
变化详情参见 Changelog。
12.1 删除
- 删除
ActiveSupport::Concurrency::Latch
类。(提交) - 删除
halt_callback_chains_on_return_false
。(提交) - 回调返回
false
时不再终止回调链。(提交)
12.2 弃用
- 温和弃用顶层
HashWithIndifferentAccess
类,换成ActiveSupport::HashWithIndifferentAccess
。(拉取请求) -
set_callback
和skip_callback
的:if
和:unless
条件选项不再接受字符串。(提交)
12.3 重要变化
- 修正 DST 发生变化时的时段解析和变迁。(提交,拉取请求)
- Unicode 更新到 9.0.0 版。(拉取请求)
- 为
#ago
添加别名Duration#before
,为#since
添加别名#after
。(拉取请求) - 添加
Module#delegate_missing_to
,把当前对象未定义的方法委托给一个代理对象。(拉取请求) - 添加
Date#all_day
,返回一个范围,表示当前日期和时间上的一整天。(拉取请求) - 为测试引入
assert_changes
和assert_no_changes
。(拉取请求) - 现在嵌套调用
travel
和travel_to
抛出异常。(拉取请求) - 更新
DateTime#change
,支持微秒和纳秒。(拉取请求)
13 荣誉榜
得益于众多贡献者,Rails 才能变得这么稳定和强健。向他们致敬!
反馈
我们鼓励您帮助提高本指南的质量。
如果看到如何错字或错误,请反馈给我们。 您可以阅读我们的文档贡献指南。
您还可能会发现内容不完整或不是最新版本。 请添加缺失文档到 master 分支。请先确认 Edge Guides 是否已经修复。 关于用语约定,请查看Ruby on Rails 指南指导。
无论什么原因,如果你发现了问题但无法修补它,请创建 issue。
最后,欢迎到 rubyonrails-docs 邮件列表参与任何有关 Ruby on Rails 文档的讨论。