2023 年 10 月 5 日,星期四

Rails 7.1:Dockerfile、自带身份验证、更多异步查询等!

发布者:rafaelfranca

Rails World 活动刚刚开始,我们正在与社区齐聚一堂,共同庆祝 Rails 成立 20 周年以及 Rails 7.1 的发布。

在此次发布中,自 Rails 7.0 以来,已有 超过五千次提交,由 超过 800 名贡献者 完成,因此 Packed with new features and improvements(包含大量新功能和改进)。

新应用程序的 Dockerfiles

现在,当您运行 rails new 时,Rails 将生成部署应用程序所需的所有 Dockerfile,以使用 Kamal 或任何其他基于 Docker 的部署设置。这些 Dockerfile 针对生产环境进行了优化,具备适当的缓存层、多阶段构建以最小化镜像大小,以及无论您是否使用 JavaScript 构建环境所需的全部依赖项。

构建您自己的身份验证改进

为了补充 has_secure_password,Rails 7.1 带来了新功能,帮助开发者构建自己的身份验证系统。

首先,normalizes 声明了属性的规范化。这在将属性保存到数据库之前对其进行规范化非常有用。

class User < ApplicationRecord
  normalizes :email, with: -> email { email.strip.downcase }
end

user = User.create(email: " CRUISE-CONTROL@EXAMPLE.COM\n")
user.email                  # => "cruise-control@example.com"

其次,authenticate_by 可在控制器中验证用户时,防止常见的时序攻击。

User.authenticate_by(email: "rafael@rubyonrails.org", password: "railsrocks")

第三,generates_token_for 可用于实现诸如密码重置、电子邮件确认以及其他需要一次性令牌的功能。

class User < ApplicationRecord
  has_secure_password

  generates_token_for :password_reset, expires_in: 15.minutes do
    # Last 10 characters of password salt, which changes when password is updated:
    password_salt&.last(10)
  end
end

user = User.first

token = user.generate_token_for(:password_reset)
User.find_by_token_for(:password_reset, token) # => user
# 16 minutes later...
User.find_by_token_for(:password_reset, token) # => nil

最后,has_secure_password 现在可以在更新密码时自动验证当前密码。这对于检查试图更新密码的用户是否知道当前密码非常有用。

# Schema: User(name:string, password_digest:string)
class User < ActiveRecord::Base
  has_secure_password
end

user = User.new(name: "rafael", password: "railsrocks", password_confirmation: "railsrocks")
user.save                                                                      # => true
user.update(password: "pwn3d", password_challenge: "")                         # => false, challenge doesn't authenticate
user.update(password: "railsGetsEvenBetter", password_challenge: "railsrocks") # => true

Active Record 的更多异步查询

Active Record 中对异步查询的 支持得到了极大的扩展。这使得并行运行多个慢速查询,特别是那些侧重于计算的查询,变得更加容易,同时允许请求的处理继续进行。有新的方法用于异步聚合(如 countsum 等)、返回单个记录的方法,以及除了 Relation 之外的其他方法。

  • async_count
  • async_sum
  • async_minimum
  • async_maximum
  • async_average
  • async_pluck
  • async_pick
  • async_ids
  • async_find_by_sql
  • async_count_by_sql

内置支持 Trilogy MySQL 适配器

Trilogy 是一个由 GitHub 创建的新的 Rails MySQL 数据库适配器,旨在提高现有 mysql2 选项的性能、灵活性和嵌入便捷性。它已在 GitHub 和 Shopify 的生产环境中使用,现在 Rails 中开箱即用地支持它作为一种选项。从下一个 Rails 主要版本开始,它很可能成为新的默认选项。

Active Record 支持复合主键

Shopify 通过切换到复合主键,将其最大表上常见查询的性能提高了 5-6 倍,并将慢速查询的数量减少了 80%。权衡是插入可能会显著变慢,但对于读写比非常高的超大表来说,这可能是一个巨大的改进。这项工作已被提取并全面支持 Active Record 中的复合主键。

使用 perform_all_later 批量入队大量作业

Active Job 中的 perform_all_later 方法的添加旨在简化同时入队大量作业的过程。这一强大的新增功能允许您高效地入队作业,而无需触发回调。当您需要一次性入队一批作业时,这尤其有用,可以减少与队列数据存储进行多次往返的开销。

引入 config.autoload_libconfig.autoload_lib_once 以增强自动加载

引入了一个新的配置方法 config.autoload_lib(ignore:)。此方法用于增强应用程序的自动加载路径,包括默认不包含的 lib 目录。此外,新应用程序会生成 config.autoload_lib(ignore: %w(assets tasks))。(此功能不适用于引擎。)

支持 Bun

您现在可以使用 Bun 作为您的 JavaScript 运行时来生成新的应用程序。为此,您可以将 --javascript=bun 选项传递给 rails new

庆祝本次发布并展望下一个版本

Rails 7.1 已经发布,但我们已经开始考虑下一个版本了。我们将在 Rails World 上分享一些我们的想法,并将与社区进行面对面交流,讨论想法并收集一些反馈。

我们期待着接下来的发展,希望您也是如此!