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 更轻松地与 JavaScript 资产捆绑器 Webpack 集成。在生成新应用程序时使用 --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 方法允许自定义模型的复数映射。
resource :basket
resolve("Basket") { [:basket] }
<%= form_for @basket do |form| %>
<!-- basket form -->
<% end %>
这将生成单数 URL /basket 而不是通常的 /baskets/:id。
direct 方法允许创建自定义 URL 助手。
direct(:homepage) { "https://rubyonrails.cn" }
homepage_url # => "https://rubyonrails.cn"
块的返回值必须是 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 %>
<%# Will generate %>
<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 %>
<%# Will generate %>
<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 %>
<%# Will generate %>
<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 %>
<%# Will generate %>
<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 连接包装在数据库事务中。
当测试派生出额外的线程,并且这些线程获取数据库连接时,这些连接现在会得到特殊处理
线程将共享单个连接,该连接位于受管事务中。这确保所有线程都以相同的状态查看数据库,忽略最外层事务。以前,例如,这些额外的连接无法看到 fixture 行。
当线程进入嵌套事务时,它将暂时独占使用连接,以保持隔离。
如果您的测试目前依赖于在派生线程中获取单独的、事务外的连接,您需要切换到更明确的连接管理。
如果您的测试派生线程并且这些线程在同时使用显式数据库事务时进行交互,此更改可能会引入死锁。
禁用此新行为的简单方法是禁用受影响的任何测试用例上的事务性测试。
4. Railties
有关详细更改,请参阅更改日志。
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 binstub 和 package.json 在新应用中添加 Yarn 支持。(拉取请求)
通过
--webpack选项在新应用中添加 Webpack 支持,该选项将委托给 rails/webpacker gem。(拉取请求)如果未提供
--skip-git选项,则在生成新应用时初始化 Git 仓库。(拉取请求)在
config/secrets.yml.enc中添加加密的秘密。(拉取请求)在
rails initializers中显示 railtie 类名。(拉取请求)
5. Action Cable
有关详细更改,请参阅更改日志。
5.1. 值得注意的更改
在
cable.yml中的 Redis 和事件驱动的 Redis 适配器中添加了对channel_prefix的支持,以避免在使用相同 Redis 服务器与多个应用程序时出现名称冲突。(拉取请求)添加
ActiveSupport::Notifications钩子以广播数据。(拉取请求)
6. Action Pack
有关详细更改,请参阅更改日志。
6.1. 移除
在
ActionDispatch::IntegrationTest和ActionController::TestCase类中,删除了对#process、#get、#post、#patch、#put、#delete和#head中非关键字参数的支持。(提交,提交)删除了已弃用的
ActionDispatch::Callbacks.to_prepare和ActionDispatch::Callbacks.to_cleanup。(提交)删除了与控制器过滤器相关的已弃用方法。(提交)
删除了在
ActionController::Parameters上调用HashWithIndifferentAccess方法的已弃用支持。(提交)
6.2. 弃用
- 已弃用
config.action_controller.raise_on_unfiltered_parameters。它在 Rails 5.1 中没有任何作用。(提交)
6.3. 显著变更
向路由 DSL 添加了
direct和resolve方法。(拉取请求)添加了一个新的
ActionDispatch::SystemTestCase类,用于在应用程序中编写系统测试。(拉取请求)
7. Action View
有关详细更改,请参阅更改日志。
7.1. 移除
删除了
ActionView::Template::Error中已弃用的#original_exception。(提交)从
strip_tags中删除选项encode_special_chars这个名称不当的选项。(拉取请求)
7.2. 弃用
- 弃用 Erubis ERB 处理程序,转而使用 Erubi。(拉取请求)
7.3. 显著变更
原始模板处理程序(Rails 5 中的默认模板处理程序)现在输出 HTML 安全字符串。(提交)
更改
datetime_field和datetime_field_tag以生成datetime-local字段。(拉取请求)HTML 标签的新 Builder 样式语法(
tag.div、tag.br等)(拉取请求)添加
form_with以统一form_tag和form_for的用法。(拉取请求)向
current_page?添加check_parameters选项。(拉取请求)
8. Action Mailer
有关详细更改,请参阅更改日志。
8.1. 值得注意的更改
允许在包含附件且正文内联设置时设置自定义内容类型。(拉取请求)
允许将 lambda 作为值传递给
default方法。(提交)添加了对邮件发送器的参数化调用的支持,以在不同的邮件发送器操作之间共享 before 过滤器和默认值。(提交)
将传入的参数通过
args键传递给邮件发送器操作的process.action_mailer事件。(拉取请求)
9. Active Record
有关详细更改,请参阅更改日志。
9.1. 移除
删除了对同时向
ActiveRecord::QueryMethods#select传递参数和块的支持。(提交)删除了已弃用的
activerecord.errors.messages.restrict_dependent_destroy.one和activerecord.errors.messages.restrict_dependent_destroy.manyi18n 作用域。(提交)删除了奇异和集合关联读取器中已弃用的强制重新加载参数。(提交)
删除了对将列传递给
#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来计数记录,而不是默默地忽略传递的块。(拉取请求)使用
psql命令传递"-v ON_ERROR_STOP=1"标志,以不抑制 SQL 错误。(拉取请求)添加
ActiveRecord::Base.connection_pool.stat。(拉取请求)直接继承自
ActiveRecord::Migration会引发错误。请指定编写迁移时使用的 Rails 版本。(提交)当
through关联具有模糊的反射名称时会引发错误。(提交)
10. Active Model
有关详细更改,请参阅更改日志。
10.1. 移除
删除了
ActiveModel::Errors中已弃用的方法。(提交)删除了长度验证器中已弃用的
:tokenizer选项。(提交)删除了在返回值为 false 时停止回调的已弃用行为。(提交)
10.2. 值得注意的更改
- 分配给模型属性的原始字符串不再被错误地冻结。(拉取请求)
11. Active Job
有关详细更改,请参阅更改日志。
11.1. 移除
删除了对将适配器类传递给
.queue_adapter的已弃用支持。(提交)删除了
ActiveJob::DeserializationError中已弃用的#original_exception。(提交)
11.2. 值得注意的更改
通过
ActiveJob::Base.retry_on和ActiveJob::Base.discard_on添加了声明性异常处理。(拉取请求)在重试失败后,提供 job 实例,以便您可以在自定义逻辑中访问
job.arguments等内容。(提交)
12. Active Support
有关详细更改,请参阅更改日志。
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. 显著变更
将 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 成为一个稳定而健壮的框架。向他们所有人致敬。