1 升级到 Rails 5.1
如果您正在升级现有应用程序,最好在进行升级之前进行充分的测试覆盖。如果您还没有升级到 Rails 5.0,请先升级到 Rails 5.0,并确保您的应用程序在升级到 Rails 5.1 之前仍然正常运行。在升级时要注意的事项列表可在升级 Ruby on Rails指南中找到。
2 主要功能
2.1 Yarn 支持
Rails 5.1 允许通过 Yarn 从 npm 管理 JavaScript 依赖项。这将使得使用 React、VueJS 或其他 npm 世界的库变得更加容易。Yarn 支持与资源管道集成,以便所有依赖项都可以与 Rails 5.1 应用程序无缝地工作。
2.2 可选的 Webpack 支持
Rails 应用程序可以更轻松地使用新的 Webpacker gem 与 Webpack(一个 JavaScript 资源打包工具)集成。在生成新应用程序时,使用 --webpack
标志启用 Webpack 集成。
这与资源管道完全兼容,您可以继续使用资源管道来处理图像、字体、声音和其他资源。您甚至可以将一些 JavaScript 代码由资源管道管理,将其他代码通过 Webpack 处理。所有这些都由默认启用的 Yarn 管理。
2.3 jQuery 不再是默认依赖项
在早期的Rails版本中,默认情况下需要使用jQuery来提供data-remote
、data-confirm
和其他Rails无侵入式JavaScript功能。现在不再需要,因为UJS已经重写为使用纯粹的JavaScript。这段代码现在作为rails-ujs
内置在Action View中。
如果需要,仍然可以使用jQuery,但默认情况下不再需要。
2.4 系统测试
Rails 5.1内置了对Capybara测试的支持,以系统测试的形式。您不再需要担心配置Capybara和数据库清理策略。Rails 5.1提供了一个在Chrome中运行测试的包装器,还提供了其他功能,如失败截图。
2.5 加密的秘密
Rails现在允许以安全的方式管理应用程序秘密,受到sekrets gem的启发。
运行bin/rails secrets:setup
来设置一个新的加密秘密文件。这也会生成一个必须存储在存储库之外的主密钥。然后可以安全地将秘密本身以加密形式提交到版本控制系统中。
在生产环境中,将使用存储在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 直接和解析的路由
Rails 5.1在路由DSL中添加了两个新方法,resolve
和direct
。resolve
方法允许自定义模型的多态映射。
```ruby
资源 :basket
解析("Basket") { [:basket] } ```
<%= form_for @basket do |form| %>
<!-- 购物篮表单 -->
<% end %>
这将生成单数URL /basket
,而不是通常的 /baskets/:id
。
direct
方法允许创建自定义的URL辅助方法。
direct(:homepage) { "https://rubyonrails.org" }
homepage_url # => "https://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
用于模型实例,form_tag
用于自定义URL。
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="<帖子的标题>">
</form>
3 不兼容性
以下更改可能需要升级后立即采取行动。
3.1 使用多个连接的事务测试
事务测试现在将所有Active Record连接包装在数据库事务中。
当一个测试生成额外的线程,并且这些线程获取数据库连接时,这些连接现在会被特殊处理:
这些线程将共享一个连接,该连接位于受控事务内部。这确保所有线程在相同的数据库状态下查看数据库,忽略最外层的事务。以前,这样的额外连接无法看到fixture行,例如。
当一个线程进入嵌套事务时,它将暂时独占连接,以保持隔离。
如果您的测试当前依赖于在生成的线程中获取一个单独的、不在事务中的连接,您需要切换到更明确的连接管理。
如果您的测试生成线程并且这些线程在使用显式数据库事务时进行交互,此更改可能会引入死锁。
退出此新行为的简单方法是在受影响的测试用例上禁用事务测试。
4 Railties
请参考Changelog以获取详细的更改信息。
4.1 删除
删除已弃用的
config.static_cache_control
。 (commit)删除已弃用的
config.serve_static_files
。 (commit)删除已弃用的文件
rails/rack/debugger
。 (commit)删除已弃用的任务:
rails:update
,rails:template
,rails:template:copy
,rails:update:configs
和rails:update:bin
。 (commit)删除
routes
任务的已弃用的CONTROLLER
环境变量。 (commit)从
rails new
命令中删除了-j(--javascript)选项。 (Pull Request)
4.2 显著更改
在
config/secrets.yml
中添加了一个共享部分,将在所有环境中加载。 (commit)现在使用所有键作为符号加载配置文件
config/secrets.yml
。 (Pull Request)从默认堆栈中删除了jquery-rails。默认的UJS适配器是随Action View一起提供的rails-ujs。 (Pull Request)
在新应用程序中添加了对Yarn的支持,包括yarn binstub和package.json。 (Pull Request)
通过
--webpack
选项在新应用中添加 Webpack 支持,该选项将委托给 rails/webpacker gem。 (Pull Request)在生成新应用时初始化 Git 仓库,如果未提供
--skip-git
选项。 (Pull Request)在
config/secrets.yml.enc
中添加加密的 secrets。 (Pull Request)在
rails initializers
中显示 railtie 类名。 (Pull Request)
5 Action Cable
详细更改请参阅Changelog。
5.1 主要更改
在
cable.yml
中为 Redis 和事件驱动的 Redis 适配器添加对channel_prefix
的支持,以避免在多个应用程序中使用相同的 Redis 服务器时发生名称冲突。 (Pull Request)为广播数据添加
ActiveSupport::Notifications
钩子。 (Pull Request)
6 Action Pack
详细更改请参阅Changelog。
6.1 移除
在
ActionDispatch::IntegrationTest
和ActionController::TestCase
类中移除对#process
、#get
、#post
、#patch
、#put
、#delete
和#head
的非关键字参数的支持。 (Commit, Commit)移除已弃用的
ActionDispatch::Callbacks.to_prepare
和ActionDispatch::Callbacks.to_cleanup
。 (Commit)移除与控制器过滤器相关的已弃用方法。 (Commit)
移除在
ActionController::Parameters
上调用HashWithIndifferentAccess
方法的已弃用支持。 (Commit)
6.2 弃用
- 弃用
config.action_controller.raise_on_unfiltered_parameters
。在 Rails 5.1 中没有任何效果。 (Commit)
6.3 主要更改
在路由 DSL 中添加
direct
和resolve
方法。 (Pull Request)添加新的
ActionDispatch::SystemTestCase
类,用于在应用程序中编写系统测试。 (Pull Request)
7 Action View
详细更改请参阅Changelog。
7.1 移除
移除在
ActionView::Template::Error
中的已弃用的#original_exception
。 (commit)从
strip_tags
中删除encode_special_chars
选项的误导。 (Pull Request)
7.2 弃用
- 弃用 Erubis ERB 处理程序,改用 Erubi。 (Pull Request)
7.3 主要更改
原始模板处理程序(在 Rails 5 中的默认模板处理程序)现在输出 HTML 安全字符串。 (commit)
将
datetime_field
和datetime_field_tag
更改为生成datetime-local
字段。 (Pull Request)HTML 标签的新 Builder 风格语法(
tag.div
、tag.br
等)。 (Pull Request)添加
form_with
以统一form_tag
和form_for
的用法。 (Pull Request)在
current_page?
中添加check_parameters
选项。 (Pull Request)
8 Action Mailer
详细更改请参考Changelog。
8.1 主要更改
允许在包含附件并且正文设置为内联时设置自定义内容类型。 (Pull Request)
允许将lambda作为
default
方法的值传递。 (Commit)添加对邮件发送器进行参数化调用的支持,以共享前置过滤器和默认值。 (Commit)
将传入的参数传递给邮件发送器动作的
process.action_mailer
事件,放在args
键下。 (Pull Request)
9 Active Record
详细更改请参考Changelog。
9.1 移除
移除将参数和块同时传递给
ActiveRecord::QueryMethods#select
的支持。 (Commit)移除已弃用的
activerecord.errors.messages.restrict_dependent_destroy.one
和activerecord.errors.messages.restrict_dependent_destroy.many
的i18n范围。 (Commit)移除单数和集合关联读取器中已弃用的强制重新加载参数。 (Commit)
移除从
#quote
中传递列的已弃用支持。 (Commit)移除从
#tables
中的name
参数。 (Commit)移除
#tables
和#table_exists?
的已弃用行为,只返回表而不返回视图。 (Commit)移除
ActiveRecord::StatementInvalid#initialize
和ActiveRecord::StatementInvalid#original_exception
中已弃用的original_exception
参数。 (Commit)移除在查询中将类作为值传递的已弃用支持。 (Commit)
移除使用逗号进行LIMIT查询的已弃用支持。 (Commit)
移除
#destroy_all
中的conditions
参数。 (Commit)移除
#delete_all
中的conditions
参数。 (Commit)移除
#load_schema_for
方法,改用#load_schema
。 (Commit)移除
#raise_in_transactional_callbacks
配置。 (Commit)移除
#use_transactional_fixtures
配置。 (Commit)
9.2 弃用
弃用
error_on_ignored_order_or_limit
标志,改用error_on_ignored_order
。 (Commit)弃用
sanitize_conditions
,改用sanitize_sql
。 (Pull Request)弃用连接适配器上的
supports_migrations?
。 (Pull Request)弃用
Migrator.schema_migrations_table_name
,改用SchemaMigration.table_name
。 (Pull Request)弃用在引号和类型转换中使用
#quoted_id
。 (Pull Request)弃用将
default
参数传递给#index_name_exists?
方法。 (拉取请求)
9.3 显著变化
将默认主键更改为BIGINT。 (拉取请求)
支持MySQL 5.7.5+和MariaDB 5.2.0+的虚拟/生成列。 (提交)
在批处理中添加对限制的支持。 (提交)
事务测试现在将所有Active Record连接包装在数据库事务中。 (拉取请求)
默认情况下跳过
mysqldump
命令输出中的注释。 (拉取请求)修复
ActiveRecord::Relation#count
方法,当传递一个块作为参数时,使用Ruby的Enumerable#count
方法进行计数,而不是静默忽略传递的块。 (拉取请求)在
psql
命令中传递"-v ON_ERROR_STOP=1"
标志,以不抑制SQL错误。 (拉取请求)添加
ActiveRecord::Base.connection_pool.stat
方法。 (拉取请求)直接从
ActiveRecord::Migration
继承将引发错误。指定编写迁移的Rails版本。 (提交)当
through
关联具有模糊的反射名称时,将引发错误。 (提交)
10 Active Model
请参阅更改日志以获取详细的更改信息。
10.1 移除
10.2 显著变化
- 不再错误地冻结分配给模型属性的原始字符串。 (拉取请求)
11 Active Job
请参阅更改日志以获取详细的更改信息。
11.1 移除
移除了将适配器类传递给
.queue_adapter
方法的弃用支持。 (提交)移除了
ActiveJob::DeserializationError
中的弃用#original_exception
方法。 (提交)
11.2 显著变化
通过
ActiveJob::Base.retry_on
和ActiveJob::Base.discard_on
添加声明式异常处理。 (拉取请求)在重试失败后的自定义逻辑中,提供作业实例以便访问诸如
job.arguments
之类的内容。 (提交)
12 Active Support
请参阅更改日志以获取详细的更改信息。
12.1 移除
移除了
ActiveSupport::Concurrency::Latch
类。 (提交)移除了
halt_callback_chains_on_return_false
。 (提交)移除了当返回值为false时中止回调的弃用行为。 (提交)
弃用
顶级
HashWithIndifferentAccess
类已被软弃用,推荐使用ActiveSupport::HashWithIndifferentAccess
类。 (拉取请求)弃用在
set_callback
和skip_callback
的:if
和:unless
条件选项中传递字符串。 (提交)
12.2 显著变化
更新Unicode到版本9.0.0。 (拉取请求)
添加了
Duration#before
和#after
作为#ago
和#since
的别名。 (拉取请求)添加了
Module#delegate_missing_to
,将当前对象未定义的方法调用委托给代理对象。 (拉取请求)添加了
Date#all_day
,返回表示当前日期和时间的整天范围。 (拉取请求)引入了
assert_changes
和assert_no_changes
方法用于测试。 (拉取请求)travel
和travel_to
方法现在在嵌套调用时会引发异常。 (拉取请求)更新
DateTime#change
以支持usec和nsec。 (拉取请求)
13 致谢
请参阅Rails的完整贡献者列表,感谢所有为Rails付出了许多时间的人,使其成为一个稳定和强大的框架。向他们致敬。
反馈
欢迎您帮助改进本指南的质量。
如果您发现任何拼写错误或事实错误,请贡献您的意见。 要开始,请阅读我们的 文档贡献 部分。
您还可能会发现不完整的内容或过时的内容。 请为主要内容添加任何缺失的文档。请先检查 Edge 指南,以验证问题是否已经修复或尚未修复。 请参阅 Ruby on Rails 指南准则 以了解样式和规范。
如果您发现需要修复但无法自行修复的问题,请 提交问题。
最后但同样重要的是,欢迎您在 官方 Ruby on Rails 论坛 上讨论有关 Ruby on Rails 文档的任何问题。