1 升级到 Rails 4.1
如果你正在升级现有的应用程序,在开始之前拥有良好的测试覆盖率是一个好主意。你还应该先升级到 Rails 4.0(如果你还没有升级),并确保你的应用程序在尝试更新到 Rails 4.1 之前仍然按预期运行。在升级时需要注意的事项列表在 升级 Ruby on Rails 指南中提供。
2 主要功能
2.1 Spring 应用程序预加载器
Spring 是一个 Rails 应用程序预加载器。它通过在后台保持应用程序运行来加快开发速度,因此你无需在每次运行测试、rake 任务或迁移时都启动它。
新的 Rails 4.1 应用程序将附带“Spring 化”的 binstubs。这意味着 bin/rails
和 bin/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/
像你对格式一样响应操作中的变体
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 来查看电子邮件的外观,该 URL 会渲染它们。
你实现一个预览类,其方法返回你想要检查的邮件对象
class NotifierPreview < ActionMailer::Preview
def welcome
Notifier.welcome(User.first)
end
end
预览在 https://127.0.0.1:3000/rails/mailers/notifier/welcome 中可用,在 https://127.0.0.1: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:uncommitted
和rake test:recent
。
3.2 显著更改
现在默认情况下为新的应用程序安装了 Spring 应用程序预加载器。它使用
Gemfile
的 development 组,因此不会安装在生产环境中。(拉取请求)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
。(Pull Request)#url_for
接收一个包含选项的哈希作为数组。(Pull Request)添加了
session#fetch
方法,其行为类似于 Hash#fetch,不同之处在于返回值始终保存到会话中。(Pull Request)将 Action View 与 Action Pack 完全分离。(Pull Request)
记录了受深度混淆影响的键。(Pull Request)
新的配置选项
config.action_dispatch.perform_deep_munge
用于选择退出参数“深度混淆”,该混淆用于解决安全漏洞 CVE-2013-0155。(Pull Request)新的配置选项
config.action_dispatch.cookies_serializer
用于指定签署和加密 Cookie 罐的序列化器。(Pull Requests 1, 2 / 更多详情)添加了
render :plain
、render :html
和render :body
。(Pull Request / 更多详情)
5 Action Mailer
有关详细信息变更,请参阅 变更日志。
5.1 值得注意的变更
添加了基于 37 Signals mail_view gem 的邮件预览功能。(Commit)
检测 Action Mailer 消息的生成。生成消息所花费的时间将写入日志。(Pull Request)
6 Active Record
有关详细信息变更,请参阅 变更日志。
6.1 移除
删除了对以下
SchemaCache
方法的弃用空传递:primary_keys
、tables
、columns
和columns_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_updates
、partial_updates?
和partial_updates=
方法。删除了弃用的
scoped
方法。删除了弃用的
default_scopes?
方法。删除了在 4.0 中弃用的隐式联接引用。
删除了
activerecord-deprecated_finders
作为依赖项。有关更多信息,请参阅 该 gem 的 README。删除了
implicit_readonly
的用法。请使用readonly
方法明确标记记录为readonly
。(Pull Request)
6.2 弃用
弃用了
quoted_locking_column
方法,该方法在任何地方都没有使用。弃用了
ConnectionAdapters::SchemaStatements#distinct
,因为它不再被内部使用。(Pull Request)弃用了
rake db:test:*
任务,因为测试数据库现在已自动维护。请参阅 railties 版本说明。(Pull Request)弃用了未使用的
ActiveRecord::Base.symbolized_base_class
和ActiveRecord::Base.symbolized_sti_name
,没有替换。 Commit
6.3 值得注意的变更
- 默认范围不再被链式条件覆盖。
在此更改之前,当您在模型中定义 default_scope
时,它会被同一字段中的链式条件覆盖。现在它像其他范围一样合并。 更多详情。
添加了
ActiveRecord::Base.to_param
,用于方便地从模型的属性或方法派生“漂亮”的 URL。(Pull Request)添加了
ActiveRecord::Base.no_touching
,它允许忽略对模型的触碰。(Pull Request)统一了
MysqlAdapter
和Mysql2Adapter
的布尔类型转换。type_cast
将为true
返回1
,为false
返回0
。(Pull Request).unscope
现在删除了default_scope
中指定的条件。(Commit)添加了
ActiveRecord::QueryMethods#rewhere
,它将覆盖现有的命名 where 条件。(Commit)扩展了
ActiveRecord::Base#cache_key
以接受可选的时间戳属性列表,其中最高值将被使用。(Commit)添加了
ActiveRecord::Base#enum
用于声明枚举属性,这些属性的值映射到数据库中的整数,但可以通过名称查询。(Commit)在写入时类型转换 JSON 值,以便该值与从数据库中读取一致。(Pull Request)
在写入时类型转换 hstore 值,以便该值与从数据库中读取一致。(Commit)
使
next_migration_number
可用于第三方生成器。(Pull Request)调用
update_attributes
现在将在它收到nil
参数时抛出ArgumentError
。更具体地说,如果传递给它的参数没有响应stringify_keys
,它将抛出错误。(Pull Request)CollectionAssociation#first
/#last
(例如has_many
)使用LIMIT
ed 查询来获取结果,而不是加载整个集合。(Pull Request)Active Record 模型类上的
inspect
不会启动新的连接。这意味着,当数据库丢失时,调用inspect
不会再抛出异常。(Pull Request)删除了
count
的列限制,如果 SQL 无效,让数据库抛出异常。(Pull Request)Rails 现在自动检测反向关联。如果您没有在关联上设置
:inverse_of
选项,那么 Active Record 将基于启发式方法猜测反向关联。(Pull Request)在 ActiveRecord::Relation 中处理别名属性。当使用符号键时,ActiveRecord 现在将别名属性名转换为数据库中使用的实际列名。(Pull Request)
夹具文件中不再评估 ERB,评估上下文不是主对象。多个夹具使用的助手方法应定义在
ActiveRecord::FixtureSet.context_class
中包含的模块上。(Pull Request)如果显式指定 RAILS_ENV,则不会创建或删除测试数据库。(Pull Request)
Relation
不再具有#map!
和#delete_if
等变异方法。通过调用#to_a
将其转换为Array
,然后再使用这些方法。(Pull Request)find_in_batches
、find_each
、Result#each
和Enumerable#index_by
现在返回一个可以计算其大小的Enumerator
。(Pull Request)scope
、enum
和关联现在在“危险”的名称冲突时引发异常。(Pull Request, Pull Request)second
到fifth
方法的行为类似于first
查找器。(Pull Request)使
touch
触发after_commit
和after_rollback
回调。(Pull Request)为
sqlite >= 3.8.0
启用部分索引。(Pull Request)使
change_column_null
可逆。(Commit)添加了一个标志,用于在迁移后禁用模式转储。这在生产环境中对新应用程序默认设置为
false
。(Pull Request)
7 Active Model
有关详细信息变更,请参阅 变更日志。
7.1 弃用
- 弃用
Validator#setup
。现在应该在验证器的构造函数中手动完成。(Commit)
7.2 值得注意的变更
添加了新的 API 方法
reset_changes
和changes_applied
到ActiveModel::Dirty
,用于控制更改状态。能够在定义验证时指定多个上下文。(Pull Request)
attribute_changed?
现在接受哈希以检查属性是否从给定值:from
和/或:to
更改。(Pull Request)
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_fallback`、`Time#utc_time` 和 `Time#local_time`,改用 `Time#utc` 和 `Time#local`。
已移除已弃用的 `Hash#diff`,无替代品。
已移除已弃用的 `Date#to_time_in_current_zone`,改用 `Date#in_time_zone`。
已移除已弃用的 `Proc#bind`,无替代品。
已移除已弃用的 `Array#uniq_by` 和 `Array#uniq_by!`,请改用原生 `Array#uniq` 和 `Array#uniq!`。
已移除已弃用的 `ActiveSupport::BasicObject`,请改用 `ActiveSupport::ProxyObject`。
已移除已弃用的 `BufferedLogger`,请改用 `ActiveSupport::Logger`。
已移除已弃用的 `assert_present` 和 `assert_blank` 方法,请改用 `assert object.blank?` 和 `assert object.present?`。
已移除过滤器对象的已弃用 `#filter` 方法,请改用相应方法(例如,对于前置过滤器,请改用 `#before`)。
已从默认的词形变化中移除 'cow' => 'kine' 不规则词形变化。 (提交)
8.2 弃用
已弃用 `Numeric#{ago,until,since,from_now}`,用户应明确地将值转换为 AS::Duration,例如 `5.ago` => `5.seconds.ago` (拉取请求)
已弃用 require 路径 `active_support/core_ext/object/to_json`。 请改用 `active_support/core_ext/object/json`。 (拉取请求)
已弃用 `ActiveSupport::JSON::Encoding::CircularReferenceError`。 此功能已提取到 activesupport-json_encoder gem 中。 (拉取请求 / 更多详情)
已弃用 `ActiveSupport.encode_big_decimal_as_string` 选项。 此功能已提取到 activesupport-json_encoder gem 中。 (拉取请求 / 更多详情)
已弃用自定义的 `BigDecimal` 序列化。 (拉取请求)
8.3 显著变化
`ActiveSupport` 的 JSON 编码器已重写,以利用 JSON gem,而不是用纯 Ruby 进行自定义编码。 (拉取请求 / 更多详情)
添加了 `ActiveSupport::Testing::TimeHelpers#travel` 和 `#travel_to`。 这些方法通过对 `Time.now` 和 `Date.today` 进行存根,将当前时间更改为给定时间或持续时间。
添加了 `ActiveSupport::Testing::TimeHelpers#travel_back`。 此方法通过移除 `travel` 和 `travel_to` 添加的存根,将当前时间恢复到原始状态。 (拉取请求)
添加了 `Numeric#in_milliseconds`,例如 `1.hour.in_milliseconds`,因此我们可以将它们提供给 JavaScript 函数,例如 `getTime()`。 (提交)
添加了 `Date#middle_of_day`、`DateTime#middle_of_day` 和 `Time#middle_of_day` 方法。 还添加了 `midday`、`noon`、`at_midday`、`at_noon` 和 `at_middle_of_day` 作为别名。 (拉取请求)
添加了 `Date#all_week/month/quarter/year` 用于生成日期范围。 (拉取请求)
添加了 `Time.zone.yesterday` 和 `Time.zone.tomorrow`。 (拉取请求)
添加了 `String#remove(pattern)` 作为 `String#gsub(pattern,'')` 的简写。 (提交)
添加了 `Hash#compact` 和 `Hash#compact!` 用于从哈希中移除值为 nil 的项。 (拉取请求)
`blank?` 和 `present?` 承诺返回单例。 (提交)
将新的 `I18n.enforce_available_locales` 配置默认设置为 `true`,这意味着 `I18n` 将确保传递给它的所有语言环境都必须在 `available_locales` 列表中声明。 (拉取请求)
引入了 `Module#concerning`:一种在类中自然地、低仪式地分离职责的方式。 (提交)
添加了 `Object#presence_in` 用于简化将值添加到允许列表中。 (提交)
9 致谢
查看 Rails 的完整贡献者列表,了解为使 Rails 成为稳定而强大的框架而付出了大量时间和精力的众多人士。 向他们致敬。