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/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/
在 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_controllerrake 任务。移除了已弃用的
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的开发组,因此不会在生产环境中安装。(拉取请求)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 罐的序列化器。(拉取请求 1,2 / 更多详情)添加了
render :plain,render :html和render :body。(拉取请求 / 更多详情)
5. Action Mailer
有关详细变更,请参阅变更日志。
5.1. 值得注意的变更
6. Active Record
有关详细变更,请参阅变更日志。
6.1. 移除
移除了对以下
SchemaCache方法已弃用的 nil 传递: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。(拉取请求)
6.2. 弃用
弃用了未使用的
quoted_locking_column方法。弃用了
ConnectionAdapters::SchemaStatements#distinct,因为它不再被内部使用。(拉取请求)弃用了
rake db:test:*任务,因为测试数据库现在会自动维护。请参阅 railties 发行说明。(拉取请求)弃用未使用的
ActiveRecord::Base.symbolized_base_class和ActiveRecord::Base.symbolized_sti_name,无替代。 提交
6.3. 显著变更
- 默认作用域不再被链式条件覆盖。
在此更改之前,当您在模型中定义 default_scope 时,它会被同一字段中的链式条件覆盖。现在它像任何其他作用域一样合并。更多详细信息。
添加了
ActiveRecord::Base.to_param,用于方便地从模型属性或方法派生“漂亮”的 URL。(拉取请求)添加了
ActiveRecord::Base.no_touching,允许忽略模型的触摸。(拉取请求)统一
MysqlAdapter和Mysql2Adapter的布尔类型转换。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_batches、find_each、Result#each和Enumerable#index_by现在返回一个可以计算其大小的Enumerator。(拉取请求)second到fifth方法的行为类似于first查找器。(拉取请求)使
touch触发after_commit和after_rollback回调。(拉取请求)为
sqlite >= 3.8.0启用部分索引。(拉取请求)使
change_column_null可回滚。(提交)添加了一个标志,用于在迁移后禁用模式转储。对于新应用程序,此功能在生产环境中默认为
false。(拉取请求)
7. Active Model
有关详细变更,请参阅变更日志。
7.1. 弃用
- 弃用
Validator#setup。现在应在验证器的构造函数中手动完成此操作。(提交)
7.2. 值得注意的变更
向
ActiveModel::Dirty添加了新的 API 方法reset_changes和changes_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_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用于 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。改为 requireactive_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,这样我们就可以将其提供给像getTime()这样的 JavaScript 函数。(提交)添加了
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 成为一个稳定而健壮的框架。向他们所有人致敬。