更多内容请访问 rubyonrails.org:

Ruby on Rails 4.1 发行说明

Rails 4.1 中的亮点

  • Spring 应用预加载器
  • config/secrets.yml
  • Action Pack 变体
  • Action Mailer 预览

这些发行说明仅涵盖主要变更。要了解各种错误修复和变更,请参阅变更日志或查看 GitHub 上 Rails 主仓库中的提交列表

1. 升级到 Rails 4.1

如果您正在升级现有应用,最好在升级前拥有良好的测试覆盖率。如果您尚未升级到 Rails 4.0,您也应该首先升级到 Rails 4.0,并确保您的应用在尝试升级到 Rails 4.1 之前仍按预期运行。在升级 Ruby on Rails 指南中提供了升级时需要注意的事项列表。

2. 主要特性

2.1. Spring 应用预加载器

Spring 是一个 Rails 应用预加载器。它通过让您的应用在后台运行来加速开发,这样您就不需要在每次运行测试、rake 任务或迁移时都启动它。

新的 Rails 4.1 应用将附带“springified”的 binstubs。这意味着 bin/railsbin/rake 将自动利用预加载的 spring 环境。

运行 rake 任务

$ bin/rake test:models

运行 Rails 命令

$ bin/rails console

Spring 内省

$ bin/spring status
Spring is running:

 1182 spring server | my_app | started 29 mins ago
 3656 spring app    | my_app | started 23 secs ago | test mode
 3746 spring app    | my_app | started 10 secs ago | development mode

请查看 Spring README 以查看所有可用功能。

有关如何将现有应用迁移到使用此功能,请参阅升级 Ruby on Rails 指南。

2.2. config/secrets.yml

Rails 4.1 在 config 文件夹中生成一个新的 secrets.yml 文件。默认情况下,此文件包含应用的 secret_key_base,但它也可以用于存储其他秘密,例如外部 API 的访问密钥。

添加到此文件的秘密可以通过 Rails.application.secrets 访问。例如,使用以下 config/secrets.yml

development:
  secret_key_base: 3b7cd727ee24e8444053437c36cc66c3
  some_api_key: SOMEKEY

Rails.application.secrets.some_api_key 在开发环境中返回 SOMEKEY

有关如何将现有应用迁移到使用此功能,请参阅升级 Ruby on Rails 指南。

2.3. Action Pack 变体

我们经常希望为手机、平板电脑和桌面浏览器渲染不同的 HTML/JSON/XML 模板。变体使其变得容易。

请求变体是请求格式的特化,例如 :tablet:phone:desktop

您可以在 before_action 中设置变体

request.variant = :tablet if request.user_agent =~ /iPad/

在 action 中响应变体,就像您响应格式一样

respond_to do |format|
  format.html do |html|
    html.tablet # renders app/views/projects/show.html+tablet.erb
    html.phone { extra_setup; render ... }
  end
end

为每种格式和变体提供单独的模板

app/views/projects/show.html.erb
app/views/projects/show.html+tablet.erb
app/views/projects/show.html+phone.erb

您还可以使用内联语法简化变体定义

respond_to do |format|
  format.js         { render "trash" }
  format.html.phone { redirect_to progress_path }
  format.html.none  { render "trash" }
end

2.4. Action Mailer 预览

Action Mailer 预览提供了一种通过访问特殊 URL 来渲染电子邮件,从而查看电子邮件外观的方法。

您实现一个预览类,其方法返回您想要检查的邮件对象

class NotifierPreview < ActionMailer::Preview
  def welcome
    Notifier.welcome(User.first)
  end
end

预览可在 https://:3000/rails/mailers/notifier/welcome 访问,列表可在 https://:3000/rails/mailers 访问。

默认情况下,这些预览类位于 test/mailers/previews 中。这可以使用 preview_path 选项进行配置。

有关详细说明,请参阅其文档

2.5. Active Record 枚举

声明一个枚举属性,其中值映射到数据库中的整数,但可以通过名称进行查询。

class Conversation < ActiveRecord::Base
  enum status: [ :active, :archived ]
end

conversation.archived!
conversation.active? # => false
conversation.status  # => "archived"

Conversation.archived # => Relation for all archived Conversations

Conversation.statuses # => { "active" => 0, "archived" => 1 }

有关详细说明,请参阅其文档

2.6. 消息验证器

消息验证器可用于生成和验证签名消息。这对于安全传输敏感数据(如记住我令牌等)很有用。

方法 Rails.application.message_verifier 返回一个新的消息验证器,该验证器使用从 secret_key_base 和给定消息验证器名称派生的密钥对消息进行签名

signed_token = Rails.application.message_verifier(:remember_me).generate(token)
Rails.application.message_verifier(:remember_me).verify(signed_token) # => token

Rails.application.message_verifier(:remember_me).verify(tampered_token)
# raises ActiveSupport::MessageVerifier::InvalidSignature

2.7. Module#concerning

一种自然、低开销的方式来分离类中的职责

class Todo < ActiveRecord::Base
  concerning :EventTracking do
    included do
      has_many :events
    end

    def latest_event
      # ...
    end

    private
      def some_internal_method
        # ...
      end
  end
end

此示例等同于在线定义 EventTracking 模块,使用 ActiveSupport::Concern 扩展它,然后将其混入 Todo 类。

有关详细说明和预期用例,请参阅其文档

2.8. 来自远程 <script> 标签的 CSRF 保护

跨站请求伪造 (CSRF) 保护现在也涵盖了带有 JavaScript 响应的 GET 请求。这可以防止第三方网站引用您的 JavaScript URL 并尝试运行它以提取敏感数据。

这意味着任何命中 .js URL 的测试现在都将失败 CSRF 保护,除非它们使用 xhr。升级您的测试以明确期望 XmlHttpRequests。将 post :create, format: :js 切换为显式的 xhr :post, :create, format: :js

3. Railties

请参阅变更日志以了解详细变更。

3.1. 移除

  • 移除了 update:application_controller rake 任务。

  • 移除了已弃用的 Rails.application.railties.engines

  • 移除了 Rails Config 中已弃用的 threadsafe!

  • 移除了已弃用的 ActiveRecord::Generators::ActiveModel#update_attributes,改用 ActiveRecord::Generators::ActiveModel#update

  • 移除了已弃用的 config.whiny_nils 选项。

  • 移除了已弃用的用于运行测试的 rake 任务:rake test:uncommittedrake test:recent

3.2. 值得注意的变更

  • 新的应用程序现在默认安装 Spring 应用程序预加载器。它使用 Gemfile 的开发组,因此不会在生产环境中安装。(拉取请求

  • BACKTRACE 环境变量用于显示测试失败的未过滤回溯。(提交

  • MiddlewareStack#unshift 公开给环境配置。(拉取请求

  • 添加了 Application#message_verifier 方法以返回消息验证器。(拉取请求

  • 默认生成的测试辅助文件所要求的 test_help.rb 文件将自动使您的测试数据库与 db/schema.rb(或 db/structure.sql)保持同步。如果重新加载模式无法解决所有待处理的迁移,它将引发错误。使用 config.active_record.maintain_test_schema = false 退出。(拉取请求

  • 引入 Rails.gem_version 作为便捷方法,返回 Gem::Version.new(Rails.version),这是一种更可靠的版本比较方式。(拉取请求

4. Action Pack

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

4.1. 移除

  • 移除了用于集成测试的已弃用的 Rails 应用程序回退,请改为设置 ActionDispatch.test_app

  • 移除了已弃用的 page_cache_extension 配置。

  • 移除了已弃用的 ActionController::RecordIdentifier,请改用 ActionView::RecordIdentifier

  • 移除了 Action Controller 中已弃用的常量

已移除 继任者
ActionController::AbstractRequest ActionDispatch::Request
ActionController::Request ActionDispatch::Request
ActionController::AbstractResponse ActionDispatch::Response
ActionController::Response ActionDispatch::Response
ActionController::Routing ActionDispatch::Routing
ActionController::Integration ActionDispatch::Integration
ActionController::IntegrationTest ActionDispatch::IntegrationTest

4.2. 值得注意的更改

  • protect_from_forgery 也阻止跨域 <script> 标签。将测试更新为使用 xhr :get, :foo, format: :js 而不是 get :foo, format: :js。(拉取请求

  • #url_for 接受一个数组内包含选项的哈希。(拉取请求

  • 添加了 session#fetch 方法,其行为类似于 Hash#fetch,不同之处在于返回的值始终保存到会话中。(拉取请求

  • Action View 完全从 Action Pack 中分离。(拉取请求

  • 记录受深度损坏影响的键。(拉取请求

  • 新的配置选项 config.action_dispatch.perform_deep_munge,用于选择退出用于解决安全漏洞 CVE-2013-0155 的 params“深度损坏”。(拉取请求

  • 新的配置选项 config.action_dispatch.cookies_serializer,用于指定签名和加密 cookie 罐的序列化器。(拉取请求 12 / 更多详情

  • 添加了 render :plain, render :htmlrender :body。(拉取请求 / 更多详情

5. Action Mailer

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

5.1. 值得注意的变更

  • 添加了基于 37 Signals mail_view gem 的邮件预览功能。(提交

  • 检测 Action Mailer 消息的生成。生成消息所需的时间将写入日志。(拉取请求

6. Active Record

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

6.1. 移除

  • 移除了对以下 SchemaCache 方法已弃用的 nil 传递:primary_keystablescolumnscolumns_hash

  • 移除了 ActiveRecord::Migrator#migrate 中已弃用的块过滤器。

  • 移除了 ActiveRecord::Migrator 中已弃用的字符串构造函数。

  • 移除了不传递可调用对象而使用 scope 的已弃用用法。

  • 移除了已弃用的 transaction_joinable=,改为使用带有 :joinable 选项的 begin_transaction

  • 移除了已弃用的 decrement_open_transactions

  • 移除了已弃用的 increment_open_transactions

  • 移除了已弃用的 PostgreSQLAdapter#outside_transaction? 方法。您可以使用 #transaction_open? 代替。

  • 移除了已弃用的 ActiveRecord::Fixtures.find_table_name,改为使用 ActiveRecord::Fixtures.default_fixture_model_name

  • 移除了 SchemaStatements 中已弃用的 columns_for_remove

  • 移除了已弃用的 SchemaStatements#distinct

  • 将已弃用的 ActiveRecord::TestCase 移到 Rails 测试套件中。该类不再是公共的,仅用于内部 Rails 测试。

  • 移除了对关联中 :dependent 的已弃用选项 :restrict 的支持。

  • 移除了对关联中已弃用的 :delete_sql:insert_sql:finder_sql:counter_sql 选项的支持。

  • 移除了 Column 中已弃用的 type_cast_code 方法。

  • 移除了已弃用的 ActiveRecord::Base#connection 方法。请确保通过类访问它。

  • 移除了 auto_explain_threshold_in_seconds 的弃用警告。

  • 移除了 Relation#count 中已弃用的 :distinct 选项。

  • 移除了已弃用的方法 partial_updatespartial_updates?partial_updates=

  • 移除了已弃用的方法 scoped

  • 移除了已弃用的方法 default_scopes?

  • 移除了在 4.0 中已弃用的隐式联接引用。

  • 移除了 activerecord-deprecated_finders 作为依赖项。请参阅 gem README 以获取更多信息。

  • 移除了 implicit_readonly 的使用。请明确使用 readonly 方法将记录标记为 readonly。(拉取请求

6.2. 弃用

  • 弃用了未使用的 quoted_locking_column 方法。

  • 弃用了 ConnectionAdapters::SchemaStatements#distinct,因为它不再被内部使用。(拉取请求

  • 弃用了 rake db:test:* 任务,因为测试数据库现在会自动维护。请参阅 railties 发行说明。(拉取请求

  • 弃用未使用的 ActiveRecord::Base.symbolized_base_classActiveRecord::Base.symbolized_sti_name,无替代。 提交

6.3. 显著变更

  • 默认作用域不再被链式条件覆盖。

在此更改之前,当您在模型中定义 default_scope 时,它会被同一字段中的链式条件覆盖。现在它像任何其他作用域一样合并。更多详细信息

  • 添加了 ActiveRecord::Base.to_param,用于方便地从模型属性或方法派生“漂亮”的 URL。(拉取请求

  • 添加了 ActiveRecord::Base.no_touching,允许忽略模型的触摸。(拉取请求

  • 统一 MysqlAdapterMysql2Adapter 的布尔类型转换。type_cast 将为 true 返回 1,为 false 返回 0。(拉取请求

  • .unscope 现在会移除 default_scope 中指定的条件。(提交

  • 添加了 ActiveRecord::QueryMethods#rewhere,它将覆盖现有的命名 where 条件。(提交

  • 扩展了 ActiveRecord::Base#cache_key,以接受一个可选的时间戳属性列表,其中将使用最高的时间戳。(提交

  • 添加了 ActiveRecord::Base#enum,用于声明枚举属性,其中值映射到数据库中的整数,但可以通过名称进行查询。(提交

  • 写入时对 JSON 值进行类型转换,使该值与从数据库读取的值保持一致。(拉取请求

  • 写入时对 hstore 值进行类型转换,使该值与从数据库读取的值保持一致。(提交

  • 使 next_migration_number 对第三方生成器可访问。(拉取请求

  • 调用 update_attributes 现在将在接收到 nil 参数时抛出 ArgumentError。更具体地说,如果传递给它的参数不能响应 stringify_keys,它将抛出错误。(拉取请求

  • CollectionAssociation#first/#last(例如 has_many)使用 LIMIT 查询来获取结果,而不是加载整个集合。(拉取请求

  • Active Record 模型类上的 inspect 不会启动新的连接。这意味着当数据库丢失时,调用 inspect 将不再引发异常。(拉取请求

  • 移除了 count 的列限制,如果 SQL 无效,则让数据库抛出异常。(拉取请求

  • Rails 现在自动检测反向关联。如果您未在关联上设置 :inverse_of 选项,则 Active Record 将根据启发式方法猜测反向关联。(拉取请求

  • 在 ActiveRecord::Relation 中处理别名属性。当使用符号键时,ActiveRecord 现在会将别名属性名转换为数据库中使用的实际列名。(拉取请求

  • fixture 文件中的 ERB 不再在主对象的上下文中进行评估。多个 fixture 使用的辅助方法应在包含在 ActiveRecord::FixtureSet.context_class 中的模块上定义。(拉取请求

  • 如果明确指定了 RAILS_ENV,则不创建或删除测试数据库。(拉取请求

  • Relation 不再具有 #map!#delete_if 等修改器方法。在使用这些方法之前,通过调用 #to_a 转换为 Array。(拉取请求

  • find_in_batchesfind_eachResult#eachEnumerable#index_by 现在返回一个可以计算其大小的 Enumerator。(拉取请求

  • scopeenum 和 Associations 现在在“危险”名称冲突时抛出异常。(拉取请求拉取请求

  • secondfifth 方法的行为类似于 first 查找器。(拉取请求

  • 使 touch 触发 after_commitafter_rollback 回调。(拉取请求

  • sqlite >= 3.8.0 启用部分索引。(拉取请求

  • 使 change_column_null 可回滚。(提交

  • 添加了一个标志,用于在迁移后禁用模式转储。对于新应用程序,此功能在生产环境中默认为 false。(拉取请求

7. Active Model

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

7.1. 弃用

  • 弃用 Validator#setup。现在应在验证器的构造函数中手动完成此操作。(提交

7.2. 值得注意的变更

  • ActiveModel::Dirty 添加了新的 API 方法 reset_changeschanges_applied,用于控制更改状态。

  • 在定义验证时指定多个上下文的能力。(拉取请求

  • attribute_changed? 现在接受一个哈希来检查属性是否从给定值 :from 和/或 :to 更改。(拉取请求

8. Active Support

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

8.1. 移除

  • 移除了 MultiJSON 依赖项。因此,ActiveSupport::JSON.decode 不再接受 MultiJSON 的选项哈希。(拉取请求 / 更多详细信息

  • 移除了对用于将自定义对象编码为 JSON 的 encode_json 钩子的支持。此功能已提取到 activesupport-json_encoder gem 中。(相关拉取请求 / 更多详细信息

  • 移除了已弃用的 ActiveSupport::JSON::Variable,无替代。

  • 移除了已弃用的 String#encoding_aware? 核心扩展(core_ext/string/encoding)。

  • 移除了已弃用的 Module#local_constant_names,改用 Module#local_constants

  • 移除了已弃用的 DateTime.local_offset,改用 DateTime.civil_from_format

  • 移除了已弃用的 Logger 核心扩展(core_ext/logger.rb)。

  • 移除了已弃用的 Time#time_with_datetime_fallbackTime#utc_timeTime#local_time,改用 Time#utcTime#local

  • 移除了已弃用的 Hash#diff,无替代。

  • 移除了已弃用的 Date#to_time_in_current_zone,改用 Date#in_time_zone

  • 移除了已弃用的 Proc#bind,无替代。

  • 移除了已弃用的 Array#uniq_byArray#uniq_by!,请改用原生的 Array#uniqArray#uniq!

  • 移除了已弃用的 ActiveSupport::BasicObject,请改用 ActiveSupport::ProxyObject

  • 移除了已弃用的 BufferedLogger,请改用 ActiveSupport::Logger

  • 移除了已弃用的 assert_presentassert_blank 方法,请改用 assert object.blank?assert object.present?

  • 移除过滤器对象的已弃用 #filter 方法,请改用对应的方法(例如,#before 用于 before 过滤器)。

  • 从默认的屈折变化中移除了“cow”=>“kine”不规则屈折变化。(提交

8.2. 弃用

8.3. 显著变更

  • ActiveSupport 的 JSON 编码器已重写,以利用 JSON gem,而不是在纯 Ruby 中进行自定义编码。(拉取请求 / 更多详细信息

  • 改进了与 JSON gem 的兼容性。(拉取请求 / 更多详细信息

  • 添加了 ActiveSupport::Testing::TimeHelpers#travel#travel_to。这些方法通过模拟 Time.nowDate.today 将当前时间更改为给定时间或持续时间。

  • 添加了 ActiveSupport::Testing::TimeHelpers#travel_back。此方法通过移除 traveltravel_to 添加的模拟,将当前时间恢复到原始状态。(拉取请求

  • 添加了 Numeric#in_milliseconds,如 1.hour.in_milliseconds,这样我们就可以将其提供给像 getTime() 这样的 JavaScript 函数。(提交

  • 添加了 Date#middle_of_dayDateTime#middle_of_dayTime#middle_of_day 方法。还添加了 middaynoonat_middayat_noonat_middle_of_day 作为别名。(拉取请求

  • 添加了 Date#all_week/month/quarter/year 用于生成日期范围。(拉取请求

  • 添加了 Time.zone.yesterdayTime.zone.tomorrow。(拉取请求

  • 添加了 String#remove(pattern) 作为 String#gsub(pattern,'') 的简写。(提交

  • 添加了 Hash#compactHash#compact!,用于从哈希中移除值为 nil 的项。(拉取请求

  • blank?present? 致力于返回单例。(提交

  • 新的 I18n.enforce_available_locales 配置默认为 true,这意味着 I18n 将确保所有传递给它的区域设置都必须在 available_locales 列表中声明。(拉取请求

  • 引入 Module#concerning:一种自然、低开销的方式来分离类中的职责。(提交

  • 添加了 Object#presence_in,以简化将值添加到允许列表。(提交

9. 鸣谢

请参阅Rails 贡献者完整列表,感谢许多人花费大量时间使 Rails 成为一个稳定而健壮的框架。向他们所有人致敬。



回到顶部