更多信息请访问 rubyonrails.org:

1 升级到 Rails 4.2

如果您要升级现有应用程序,建议在升级前拥有良好的测试覆盖率。您还应该首先升级到 Rails 4.1(如果您尚未升级),并确保您的应用程序在尝试升级到 Rails 4.2 之前能够正常运行。升级时需要注意的事项列表可在指南 升级 Ruby on Rails 中找到。

2 主要功能

2.1 Active Job

Active Job 是 Rails 4.2 中的新框架。它是在像 ResqueDelayed JobSidekiq 等排队系统之上的通用接口。

使用 Active Job API 编写的作业可以在任何支持的队列上运行,这得益于它们各自的适配器。Active Job 预先配置了一个内联运行器,它会立即执行作业。

作业通常需要将 Active Record 对象作为参数。Active Job 将对象引用作为 URI(统一资源标识符)传递,而不是序列化对象本身。新的 Global ID 库构建 URI 并查找它们引用的对象。通过在内部使用 Global ID,将 Active Record 对象作为作业参数传递可以正常工作。

例如,如果 trashable 是一个 Active Record 对象,那么此作业可以正常运行,无需进行任何序列化

class TrashableCleanupJob < ActiveJob::Base
  def perform(trashable, depth)
    trashable.cleanup(depth)
  end
end

有关更多信息,请参阅 Active Job 基础 指南。

2.2 异步邮件

基于 Active Job,Action Mailer 现在提供了一个 deliver_later 方法,它通过队列发送电子邮件,因此如果队列是异步的(默认的内联队列会阻塞),它不会阻塞控制器或模型。

使用 deliver_now 仍然可以立即发送电子邮件。

2.3 Adequate Record

Adequate Record 是一组 Active Record 中的性能改进,它使常见的 findfind_by 调用以及一些关联查询的速度提高了 2 倍。

它通过将常见的 SQL 查询缓存为准备好的语句并在类似的调用中重复使用它们来工作,从而在后续调用中跳过大部分查询生成工作。有关更多详细信息,请参阅 Aaron Patterson 的博客文章

Active Record 将在支持的操作上自动利用此功能,无需用户干预或代码更改。以下是一些受支持操作的示例

Post.find(1)  # First call generates and cache the prepared statement
Post.find(2)  # Subsequent calls reuse the cached prepared statement

Post.find_by_title('first post')
Post.find_by_title('second post')

Post.find_by(title: 'first post')
Post.find_by(title: 'second post')

post.comments
post.comments(true)

重要的是要注意,如上面的示例所示,准备好的语句不会缓存方法调用中传递的值;相反,它们会为它们提供占位符。

在以下情况下不使用缓存

  • 模型具有默认作用域
  • 模型使用单表继承
  • find 带 ID 列表,例如

    # not cached
    Post.find(1, 2, 3)
    Post.find([1,2])
    
  • find_by 带 SQL 片段

    Post.find_by('published_at < ?', 2.weeks.ago)
    

2.4 Web 控制台

使用 Rails 4.2 生成的新的应用程序现在默认情况下包含 Web 控制台 gem。Web 控制台在每个错误页面上添加了一个交互式 Ruby 控制台,并提供了一个 console 视图和控制器助手。

错误页面上的交互式控制台允许您在异常起源位置的上下文中执行代码。如果在视图或控制器中的任何地方调用 console 助手,它将在渲染完成后启动一个带最终上下文的交互式控制台。

2.5 外键支持

迁移 DSL 现在支持添加和删除外键。它们也转储到 schema.rb 中。目前,只有 mysqlmysql2postgresql 适配器支持外键。

# add a foreign key to `articles.author_id` referencing `authors.id`
add_foreign_key :articles, :authors

# add a foreign key to `articles.author_id` referencing `users.lng_id`
add_foreign_key :articles, :users, column: :author_id, primary_key: "lng_id"

# remove the foreign key on `accounts.branch_id`
remove_foreign_key :accounts, :branches

# remove the foreign key on `accounts.owner_id`
remove_foreign_key :accounts, column: :owner_id

有关完整描述,请参阅 add_foreign_keyremove_foreign_key 上的 API 文档。

3 不兼容性

以前已弃用的功能已被删除。请参阅各个组件以了解此版本中的新弃用内容。

以下更改可能需要在升级后立即采取措施。

3.1 render 带字符串参数

以前,在控制器操作中调用 render "foo/bar" 等效于 render file: "foo/bar"。在 Rails 4.2 中,这已更改为改为表示 render template: "foo/bar"。如果您需要渲染文件,请将您的代码更改为改为使用显式形式(render file: "foo/bar")。

3.2 respond_with / 类级 respond_to

respond_with 和相应的类级 respond_to 已移至 responders gem。将 gem "responders", "~> 2.0" 添加到您的 Gemfile 以使用它

# app/controllers/users_controller.rb

class UsersController < ApplicationController
  respond_to :html, :json

  def show
    @user = User.find(params[:id])
    respond_with @user
  end
end

实例级 respond_to 不受影响

# app/controllers/users_controller.rb

class UsersController < ApplicationController
  def show
    @user = User.find(params[:id])
    respond_to do |format|
      format.html
      format.json { render json: @user }
    end
  end
end

3.3 rails server 的默认主机

由于 Rack 中的更改rails server 现在默认情况下在 localhost 上监听,而不是 0.0.0.0。这应该对标准开发工作流程的影响最小,因为 http://127.0.0.1:3000https://127.0.0.1:3000 将继续像以前一样在您自己的机器上工作。

但是,通过此更改,您将无法再从另一台机器访问 Rails 服务器,例如,如果您的开发环境位于虚拟机中,而您想从主机访问它。在这种情况下,请使用 rails server -b 0.0.0.0 启动服务器以恢复旧行为。

如果您这样做,请确保正确配置您的防火墙,以使只有网络上的受信任机器才能访问您的开发服务器。

3.4 更改 render 的状态选项符号

由于 Rack 中的更改render 方法接受的 :status 选项的符号已更改

  • 306: :reserved 已被删除。
  • 413: :request_entity_too_large 已重命名为 :payload_too_large
  • 414: :request_uri_too_long 已重命名为 :uri_too_long
  • 416: :requested_range_not_satisfiable 已重命名为 :range_not_satisfiable

请记住,如果使用未知符号调用 render,则响应状态将默认为 500。

3.5 HTML 净化器

HTML 净化器已被一个新的、更强大的实现所取代,该实现基于LoofahNokogiri。新的净化器更加安全,其净化功能更强大、更灵活。

由于新算法,对于某些病态输入,净化后的输出可能会有所不同。

如果您需要旧净化器完全相同的输出,可以将rails-deprecated_sanitizer gem 添加到 Gemfile 中,以保持旧的行为。该 gem 不会发出弃用警告,因为它是可选的。

rails-deprecated_sanitizer 仅支持 Rails 4.2;它不会维护 Rails 5.0。

有关新净化器更改的更多详细信息,请参见这篇博文

3.6 assert_select

assert_select 现在基于Nokogiri。因此,一些以前有效的选择器现在不支持。如果您的应用程序使用这些拼写中的任何一种,您需要更新它们。

  • 属性选择器中的值可能需要加引号,如果它们包含非字母数字字符。

    # before
    a[href=/]
    a[href$=/]
    
    # now
    a[href="/"]
    a[href$="/"]
    
  • 从包含无效 HTML(嵌套不当的元素)的 HTML 源代码构建的 DOM 可能会有所不同。

    例如

    # content: <div><i><p></i></div>
    
    # before:
    assert_select('div > i')  # => true
    assert_select('div > p')  # => false
    assert_select('i > p')    # => true
    
    # now:
    assert_select('div > i')  # => true
    assert_select('div > p')  # => true
    assert_select('i > p')    # => false
    
  • 如果所选数据包含实体,用于比较的所选值过去是原始的(例如 AT&amp;T),现在是评估后的(例如 AT&T)。

    # content: <p>AT&amp;T</p>
    
    # before:
    assert_select('p', 'AT&amp;T')  # => true
    assert_select('p', 'AT&T')      # => false
    
    # now:
    assert_select('p', 'AT&T')      # => true
    assert_select('p', 'AT&amp;T')  # => false
    

此外,替换语法已更改。

现在您必须使用类似 CSS 的 :match 选择器

assert_select ":match('id', ?)", 'comment_1'

此外,当断言失败时,正则表达式替换看起来不同。请注意,/hello/ 在这里

assert_select(":match('id', ?)", /hello/)

变为 "(?-mix:hello)"

Expected at least 1 element matching "div:match('id', "(?-mix:hello)")", found 0..
Expected 0 to be >= 1.

有关 assert_select 的更多信息,请参见Rails Dom Testing 文档。

4 Railties

有关详细更改,请参阅变更日志

4.1 移除

  • --skip-action-view 选项已从应用程序生成器中删除。(拉取请求)

  • rails application 命令已删除,没有替代品。(拉取请求)

4.2 弃用

  • 弃用生产环境中缺少的 config.log_level。(拉取请求)

  • 弃用 rake test:all,改为 rake test,因为它现在运行 test 文件夹中的所有测试。(拉取请求)

  • 弃用 rake test:all:db,改为 rake test:db。(拉取请求)

  • 弃用 Rails::Rack::LogTailer,没有替代品。(提交)

4.3 重要更改

  • 在默认应用程序 Gemfile 中引入了 web-console。(拉取请求)

  • 为模型生成器中的关联添加了 required 选项。(拉取请求)

  • 引入了用于定义自定义配置选项的 x 命名空间

    # config/environments/production.rb
    config.x.payment_processing.schedule = :daily
    config.x.payment_processing.retries  = 3
    config.x.super_debugger              = true
    

    然后可以通过配置对象访问这些选项

    Rails.configuration.x.payment_processing.schedule # => :daily
    Rails.configuration.x.payment_processing.retries  # => 3
    Rails.configuration.x.super_debugger              # => true
    

    (提交)

  • 引入了 Rails::Application.config_for 用于加载当前环境的配置。

    # config/exception_notification.yml
    production:
      url: http://127.0.0.1:8080
      namespace: my_app_production
    development:
      url: https://127.0.0.1:3001
      namespace: my_app_development
    
    # config/environments/production.rb
    Rails.application.configure do
      config.middleware.use ExceptionNotifier, config_for(:exception_notification)
    end
    

    (拉取请求)

  • 在应用程序生成器中引入了 --skip-turbolinks 选项,以便不生成 turbolinks 集成。(提交)

  • 引入了 bin/setup 脚本,作为在引导应用程序时使用自动设置代码的约定。(拉取请求)

  • 在开发环境中将 config.assets.digest 的默认值更改为 true。(拉取请求)

  • 引入了用于注册 rake notes 的新扩展的 API。(拉取请求)

  • 引入了 after_bundle 回调,供 Rails 模板使用。(拉取请求)

  • 引入了 Rails.gem_version 作为一种方便方法来返回 Gem::Version.new(Rails.version)。(拉取请求)

5 Action Pack

有关详细更改,请参阅变更日志

5.1 移除

  • respond_with 和类级 respond_to 已从 Rails 中删除,并移至 responders gem(版本 2.0)。将 gem "responders", "~> 2.0" 添加到您的 Gemfile 中以继续使用这些功能。(拉取请求更多详细信息)

  • 删除了已弃用的 AbstractController::Helpers::ClassMethods::MissingHelperError,改为 AbstractController::Helpers::MissingHelperError。(提交)

5.2 弃用

  • 弃用了 *_path 帮助器上的 only_path 选项。(提交)

  • 弃用 assert_tagassert_no_tagfind_tagfind_all_tag,改为 assert_select。(提交)

  • 弃用了对在路由器上设置 :to 选项为符号或不包含“#”字符的字符串的支持

    get '/posts', to: MyRackApp    => (No change necessary)
    get '/posts', to: 'post#index' => (No change necessary)
    get '/posts', to: 'posts'      => get '/posts', controller: :posts
    get '/posts', to: :index       => get '/posts', action: :index
    

    (提交)

  • 弃用了对 URL 帮助器中使用字符串键的支持

    # bad
    root_path('controller' => 'posts', 'action' => 'index')
    
    # good
    root_path(controller: 'posts', action: 'index')
    

    (拉取请求)

5.3 重要更改

  • *_filter 方法系列已从文档中删除。建议使用 *_action 方法系列代替它们。

    after_filter          => after_action
    append_after_filter   => append_after_action
    append_around_filter  => append_around_action
    append_before_filter  => append_before_action
    around_filter         => around_action
    before_filter         => before_action
    prepend_after_filter  => prepend_after_action
    prepend_around_filter => prepend_around_action
    prepend_before_filter => prepend_before_action
    skip_after_filter     => skip_after_action
    skip_around_filter    => skip_around_action
    skip_before_filter    => skip_before_action
    skip_filter           => skip_action_callback
    

    如果您的应用程序当前依赖于这些方法,您应该使用替代的 *_action 方法。这些方法将在将来弃用,并最终从 Rails 中删除。

    (提交 12)

  • render nothing: true 或渲染 nil 主体不再向响应主体添加单个空格填充。(拉取请求)

  • Rails 现在会自动在 ETag 中包含模板的摘要。(拉取请求)

  • 传递到 URL 帮助器的段现在会自动转义。(提交)

  • 引入了 always_permitted_parameters 选项来配置全局允许哪些参数。此配置的默认值为 ['controller', 'action']。(拉取请求)

  • 添加了来自 RFC 4791 的 HTTP 方法 MKCALENDAR。(拉取请求)

  • *_fragment.action_controller 通知现在在有效负载中包含控制器和操作名称。(拉取请求)

  • 改进了路由错误页面,增加了对路由搜索的模糊匹配。(拉取请求)

  • 添加了用于禁用记录 CSRF 失败的选项。(拉取请求)

  • 当 Rails 服务器设置为提供静态资产时,如果客户端支持并存在预先生成的 gzip 文件(.gz),现在将提供 gzip 资产。默认情况下,资产管道为所有可压缩资产生成 .gz 文件。提供 gzip 文件可以最大程度地减少数据传输并加快资产请求速度。如果您在生产环境中从 Rails 服务器提供资产,请始终使用 CDN。(拉取请求)

  • 在集成测试中调用 process 帮助器时,路径需要有一个前导斜杠。以前您可以省略它,但这只是实现的副产品,而不是有意为之的功能,例如

    test "list all posts" do
      get "/posts"
      assert_response :success
    end
    

6 Action View

有关详细更改,请参阅变更日志

6.1 弃用

  • 弃用 AbstractController::Base.parent_prefixes。当您想要更改查找视图的位置时,请重写 AbstractController::Base.local_prefixes。(拉取请求)

  • 弃用 ActionView::Digestor#digest(name, format, finder, options = {})。参数应作为哈希而不是单独传递。(拉取请求)

6.2 重要更改

  • render "foo/bar" 现在扩展为 render template: "foo/bar" 而不是 render file: "foo/bar"。(拉取请求)

  • 表单帮助器不再围绕隐藏字段生成带有内联 CSS 的 <div> 元素。(拉取请求)

  • 引入了 #{partial_name}_iteration 特殊局部变量,供与集合一起渲染的局部变量使用。它通过 indexsizefirst?last? 方法提供对迭代当前状态的访问。(拉取请求)

  • 占位符 I18n 遵循与 label I18n 相同的约定。(拉取请求)

7 Action Mailer

有关详细更改,请参阅变更日志

7.1 弃用

  • 弃用了邮件程序中的 *_path 帮助器。始终使用 *_url 帮助器代替。(拉取请求)

  • 弃用 deliver / deliver!,改为 deliver_now / deliver_now!。(拉取请求)

7.2 重要更改

  • link_tourl_for 在模板中默认生成绝对 URL,不再需要传递 only_path: false。(提交)

  • 引入了 deliver_later,它在应用程序的队列上排队一个作业,以异步方式发送电子邮件。(拉取请求)

  • 添加了 show_previews 配置选项,用于在开发环境之外启用邮件程序预览。(拉取请求)

8 Active Record

有关详细更改,请参阅变更日志

8.1 移除

  • 删除了 cache_attributes 及其相关方法。所有属性都被缓存。(拉取请求)

  • 删除了已弃用的方法 ActiveRecord::Base.quoted_locking_column。(拉取请求)

  • 删除了已弃用的 ActiveRecord::Migrator.proper_table_name。请改用 ActiveRecord::Migration 上的 proper_table_name 实例方法。(拉取请求)

  • 删除了未使用的 :timestamp 类型。在所有情况下都将其透明地别名为 :datetime。修复了在将列类型发送到 Active Record 之外时(例如用于 XML 序列化)出现的不一致性。(拉取请求)

8.2 弃用

  • 弃用了 after_commitafter_rollback 内部对错误的吞咽。(拉取请求)

  • 弃用了对 has_many :through 关联中自动检测计数器缓存的错误支持。您应该改为在 has_manybelongs_to 关联中手动指定通过记录的计数器缓存。(拉取请求)

  • 弃用了将 Active Record 对象传递给 .find.exists?。请先对对象调用 id。(提交 12)

  • 弃用了对 PostgreSQL 范围值与排除开头的半生不熟的支持。我们目前将 PostgreSQL 范围映射到 Ruby 范围。这种转换并不完全可行,因为 Ruby 范围不支持排除开头。

    在开始处递增的当前解决方案不正确,现已弃用。对于我们不知道如何递增的子类型(例如,succ 未定义),对于排除开始处的范围,它将引发 ArgumentError。(Commit

  • 已弃用在没有连接的情况下调用 DatabaseTasks.load_schema。请改用 DatabaseTasks.load_schema_current。(Commit

  • 已弃用 sanitize_sql_hash_for_conditions,没有替代方案。使用 Relation 来执行查询和更新是首选的 API。(Commit

  • 已弃用 add_timestampst.timestamps 而不传递 :null 选项。Rails 5 中的 null: true 默认值将更改为 null: false。(Pull Request

  • 已弃用 Reflection#source_macro,没有替代方案,因为它在 Active Record 中不再需要。(Pull Request

  • 已弃用 serialized_attributes,没有替代方案。(Pull Request

  • 已弃用当不存在列时从 column_for_attribute 返回 nil。在 Rails 5.0 中,它将返回一个空对象。(Pull Request

  • 已弃用使用 .joins.preload.eager_load 与依赖于实例状态的关联(即那些使用接受参数的范围定义的关联),没有替代方案。(Commit

8.3 重点更改

  • SchemaDumpercreate_table 上使用 force: :cascade。这使得在存在外键时重新加载模式成为可能。

  • 向单数关联添加了 :required 选项,该选项在关联上定义存在验证。(Pull Request

  • ActiveRecord::Dirty 现在可以检测可变值的原地更改。Active Record 模型上的序列化属性在没有更改时不再保存。这也适用于其他类型,例如字符串列和 PostgreSQL 上的 json 列。(Pull Requests 123

  • 引入了 db:purge Rake 任务来清空当前环境的数据库。(Commit

  • 引入了 ActiveRecord::Base#validate!,如果记录无效,则会引发 ActiveRecord::RecordInvalid。(Pull Request

  • 引入了 validate 作为 valid? 的别名。(Pull Request

  • touch 现在接受多个属性,以便一次性触碰多个属性。(Pull Request

  • PostgreSQL 适配器现在在 PostgreSQL 9.4+ 中支持 jsonb 数据类型。(Pull Request

  • PostgreSQL 和 SQLite 适配器不再在字符串列上添加 255 个字符的默认限制。(Pull Request

  • 在 PostgreSQL 适配器中添加了对 citext 列类型的支持。(Pull Request

  • 在 PostgreSQL 适配器中添加了对用户创建的范围类型的支持。(Commit

  • sqlite3:///some/path 现在解析为绝对系统路径 /some/path。对于相对路径,请改用 sqlite3:some/path。(以前,sqlite3:///some/path 解析为相对路径 some/path。这种行为在 Rails 4.1 中已弃用)。(Pull Request

  • 为 MySQL 5.6 及更高版本添加了对小数秒的支持。(Pull Request 12

  • 添加了 ActiveRecord::Base#pretty_print 来美化打印模型。(Pull Request

  • ActiveRecord::Base#reload 现在与 m = Model.find(m.id) 的行为相同,这意味着它不再保留来自自定义 SELECT 的额外属性。(Pull Request

  • ActiveRecord::Base#reflections 现在返回一个带有字符串键而不是符号键的哈希表。(Pull Request

  • 迁移中的 references 方法现在支持 type 选项,用于指定外键的类型(例如 :uuid)。(Pull Request

9 Active Model

有关详细更改,请参阅 Changelog

9.1 删除

  • 已弃用 Validator#setup,没有替代方案。(Pull Request

9.2 弃用

  • 已弃用 reset_#{attribute},请改用 restore_#{attribute}。(Pull Request

  • 已弃用 ActiveModel::Dirty#reset_changes,请改用 clear_changes_information。(Pull Request

9.3 重点更改

  • 引入了 validate 作为 valid? 的别名。(Pull Request

  • ActiveModel::Dirty 中引入了 restore_attributes 方法,用于将更改的(脏的)属性恢复为它们以前的值。(Pull Request 12

  • has_secure_password 默认情况下不再禁止空白密码(即仅包含空格的密码)。(Pull Request

  • 如果启用了验证,has_secure_password 现在会验证给定密码是否少于 72 个字符。(Pull Request

10 Active Support

有关详细更改,请参阅 Changelog

10.1 删除

  • 已弃用 Numeric#agoNumeric#untilNumeric#sinceNumeric#from_now。(Commit

  • 已弃用基于字符串的 ActiveSupport::Callbacks 终止符。(Pull Request

10.2 弃用

  • 已弃用 Kernel#silence_stderrKernel#captureKernel#quietly,没有替代方案。(Pull Request

  • 已弃用 Class#superclass_delegating_accessor,请改用 Class#class_attribute。(Pull Request

  • 已弃用 ActiveSupport::SafeBuffer#prepend!,因为 ActiveSupport::SafeBuffer#prepend 现在执行相同的功能。(Pull Request

10.3 重点更改

  • 引入了新的配置选项 active_support.test_order,用于指定执行测试用例的顺序。此选项目前默认值为 :sorted,但在 Rails 5.0 中将更改为 :random。(Commit

  • Object#tryObject#try! 现在可以在块中使用,无需显式接收器。(CommitPull Request

  • travel_to 测试助手现在会将 usec 组件截断为 0。(Commit

  • 引入了 Object#itself 作为身份函数。(Commit 12

  • Object#with_options 现在可以在块中使用,无需显式接收器。(Pull Request

  • 引入了 String#truncate_words,用于按单词数量截断字符串。(Pull Request

  • 添加了 Hash#transform_valuesHash#transform_values!,以简化哈希表的值必须更改但键保持不变的常见模式。(Pull Request

  • humanize 变形词助手现在会删除任何前导下划线。(Commit

  • 引入了 Concern#class_methods 作为 module ClassMethods 的替代方案,以及 Kernel#concern,以避免 module Foo; extend ActiveSupport::Concern; end 模板。(Commit

  • 新的 指南 关于常量自动加载和重新加载。

11 鸣谢

查看 Rails 的完整贡献者列表,了解那些花了很多时间让 Rails 成为今天这样稳定而健壮的框架的许多人。向他们所有人致敬。



返回顶部