1 升级至 Rails 4.1
如果你正试著升级现有的应用程序至 Rails 4.1,最好有广的测试覆盖度。首先应先升级至 4.0,再升上 4.1。升级需要注意的事项在此篇 Ruby on Rails 升级指南可以找到。
2 主要特性
2.1 Spring 预加载应用程序
Spring 预加载你的 Rails 应用程序。保持应用程序在后台运行,如此一来运行 Rails 命令时:如测试、rake、migrate 不用每次都重启 Rails 应用程序,加速你的开发流程。
新版 Rails 4.1 应用程序出厂内建 “Spring 化” 的 binstubs(aka,运行文件,如 rails、rake)。这表示 bin/rails、bin/rake 会自动采用 Spring 预载的环境。
运行 rake 任务:
bin/rake test:models
运行 console:
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 升级指南 来了解如何在 Rails 4.1 以下使用此特性。
2.2 config/secrets.yml
Rails 4.1 会在 config/ 目录下产生新的 secrets.yml。这个文件默认存有应用程序的 secret_key_base,也可以用来存放其它 secrets,比如存放外部 API 需要用的 access keys。例子:
secrets.yml:
development: secret_key_base: "3b7cd727ee24e8444053437c36cc66c3" some_api_key: "b2c299a4a7b2fe41b6b7ddf517604a1c34"
读取:
> Rails.application.secrets => "3b7cd727ee24e8444053437c36cc66c3" > Rails.application.secrets.some_api_key => "SOMEKEY"
参考 Ruby on Rails 升级指南 来了解如何在 Rails 4.1 以下使用此特性。
2.3 Action Pack Variants
针对手机、平板、桌上型电脑及浏览器,常需要 render 不同格式的模版:html、json、xml。
Variant 简化了这件事。
Request variant 是一种特殊的 request 格式,像是 :tablet、:phone 或 :desktop。
可在 before_action 里配置 Variant:
request.variant = :tablet if request.user_agent =~ /iPad/
在 Controller action 里,回应特殊格式跟处理别的格式相同:
respond_to do |format|
format.html do |html|
html.tablet # 会 render 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
Variant 定义可以用 inline 写法来简化:
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 Preview 提供你访问特定 URL 来预览 Email 的特性,假设你有个 Notifier Mailer,首先实现预览 Notifier 用的类:
class NotifierPreview < ActionMailer::Preview
def welcome
Notifier.welcome(User.first)
end
end
如此一来便可访问 http://localhost:3000/rails/mailers/notifier/welcome 来预览 Email。
所有可预览的 Email 可在此找到:http://localhost:3000/rails/mailers
默认 preview 类的文件保存在 test/mailers/previews、可以通过 preview_path 选项来配置。
参见 Action Mailer 的文件来了解更多细节。
2.5 Active Record enums
设置一个 enum 属性,将属性映射到数据库的整数,并可通过名字查询出来:
class Conversation < ActiveRecord::Base enum status: [ :active, :archived ] end conversation.archived! conversation.active? # => false conversation.status # => "archived" Conversation.archived # => Relation for all archived Conversations
参见 active_record/enum.rb 来了解更多细节。
2.6 Message verifiers 信息验证器
信息验证器用来生成和校验签名信息,可以用来保障敏感数据(如记住我口令,朋友数据)传输的安全性。
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) # 抛出异常 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 Module,extend ActiveSupport::Concern,再混入 (mixin) Todo 类。
参见 Module#concerning 来了解更多细节。
2.8 CSRF protection from remote <script> tags
Rails 的跨站伪造请求(CSRF)防护机制现在也会保护从第三方 JavaScript 来的 GET 请求了!这预防第三方网站运行你的 JavaScript,试图窃取敏感资料。
这代表任何访问 .js URL 的测试会失败,除非你明确指定使用 xhr (XmlHttpRequests)。
post :create, format: :js
改写为
xhr :post, :create, format: :js
3 Railties
请参考 [Changelog][Railties-CHANGELOG] 来了解更多细节。
3.1 移除
移除了
update:application_controllerrake 任务。移除了
Rails.application.railties.engines。Rails 移除了
config.threadsafe!配置。移除了
ActiveRecord::Generators::ActiveModel#update_attributes, 请改用ActiveRecord::Generators::ActiveModel#update。移除了
config.whiny_nils配置。移除了用来跑测试的两个 task:
rake test:uncommitted与rake test:recent。
3.2 值得一提的变化
Spring 纳入默认 Gem,列在
Gemfile的group :development里,所以 production 环境不会安装。PR#12958BACKTRACE环境变量可看(unfiltered)测试的 backtrace。Commit可以在环境配置文件配置
MiddlewareStack#unshift。 PR#12749新增
Application#message_verifier方法来返回消息验证器。PR#12995默认生成的
test_helper.rb会requiretest_help.rb,帮你把测试的数据库与db/schema.rb(或db/structure.sql)同步。但发现尚未迁移的 migration 与 schema 不一致时会抛出错误。错误抛出与否:config.active_record.maintain_test_schema = false,参见此PR#13528。
4 Action Pack
请参考 [Changelog][AP-CHANGELOG] 来了解更多细节。
4.1 移除
移除了 Rails 针对整合测试的补救方案(fallback),请配置
ActionDispatch.test_app。移除了
config.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。PR#13345#url_for接受额外的 options,可将选项打包成 hash,放在数组传入。PR#9599新增
session#fetch方法,行为与 Hash#fetch 类似,差别在返回值永远会存回 session。 PR#12692将 Action View 从 Action Pack 里整个拿掉。 PR#11032
5 Action Mailer
请参考 Changelog 来了解更多细节。
5.1 值得一提的变化
- Action Mailer 产生 mail 的时间会写到 log 里。 PR#12556
6 Active Record
请参考 [Changelog][AR-CHANGELOG] 来了解更多细节。
6.1 移除
移除了传入
nil至右列SchemaCache的方法:primary_keys、tables、columns及columns_hash。从
ActiveRecord::Migrator#migrate移除了 block filter。从
ActiveRecord::Migrator移除了 String constructor。移除了 scope 没传 callable object 的用法。
移除了
transaction_joinable=,请改用begin_transaction加:joinable选项的组合。移除了
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 test 里。移除有
:dependent选项的关联传入:restrict选项。移除了 association 这几个选项
:delete_sql、:insert_sql、:finder_sql及:counter_sql。从 Column 移除了
type_cast_code方法。移除了
ActiveRecord::Base#connection实体方法,请透过 Class 来使用。移除了
auto_explain_threshold_in_seconds的警告。移除了
Relation#count的:distinct选项。移除了
partial_updates、partial_updates?与partial_updates=。移除了
scoped。移除了
default_scopes?。移除了隐式的 join references。
移掉
activerecord-deprecated_findersgem 的相依性。移除了
implicit_readonly。请改用readonly方法,并将 record 明确标明为readonly。 PR#10769
6.2 弃用
弃用了任何地方都没用到的
quoted_locking_column方法。弃用了 association 从 Array 获得的 bang 方法。要使用请先将 association 转成数组(
#to_a),再对元素做处理。 PR#12129。Rails 内部弃用了
ConnectionAdapters::SchemaStatements#distinct。 PR#10556弃用
rake db:test:*系列的任务,因为现在会自动配置好测试数据库。参见 Railties 的发布记。PR#13528弃用了无用的
ActiveRecord::Base.symbolized_base_class与ActiveRecord::Base.symbolized_sti_name且没有替代方案。Commit
6.3 值得一提的变化
新增
ActiveRecord::Base.to_param来显示漂亮的 URL。 PR#12891新增
ActiveRecord::Base.no_touching,可允许忽略对 Model 的 touch。 PR#12772统一了
MysqlAdapter与Mysql2Adapter的布尔转换,true会返回1,false返回0。 PR#12425unscope现在移除了default_scope规范的 conditions。Commit新增
ActiveRecord::QueryMethods#rewhere,会覆写已存在的 where 条件。Commit扩充了
ActiveRecord::Base#cache_key,可接受多个 timestamp,会使用数值最大的 timestamp。Commit新增
ActiveRecord::Base#enum,用来枚举 attributes。将 attributes 映射到数据库的整数,并可透过名字查询出来。Commit写入数据库时,JSON 会做类型转换。这样子读写才会一致。 PR#12643
写入数据库时,hstore 会做类型转换,这样子读写才会一致。Commit
next_migration_number可供第三方函式库存取。 PR#12407若是调用
update_attributes的参数有nil,则会抛出ArgumentError。更精准的说,传进来的参数,没有回应(respond_to)stringify_keys的话,会抛出错误。PR#9860CollectionAssociation#first/#last(has_many) ,Query 会使用LIMIT来限制提取的数量,而不是将整个 collection 载入出来。 PR#12137对 Active Record Model 的类别做
inspect不会去连数据库。这样当数据库不存在时,inspect才不会喷错误。PR#11014移除了
count的列限制,SQL 不正确时,让数据库自己丢出错误。 PR#10710Rails 现在会自动侦测 inverse associations。如果 association 没有配置
:inverse_of,则 Active Record 会自己猜出对应的 associaiton。PR#10886ActiveRecord::Relation会处理有别名的 attributes。当使用符号作为 key 时,Active Record 现在也会一起翻译别名的属性了,将其转成数据库内所使用的列名。PR#7839Fixtures 文件中的 ERB 不在 main 对象上下文里执行了,多个 fixtures 使用的 Helper 方法,需要定义在被
ActiveRecord::FixtureSet.context_class包含的模块里。PR#13022若是明确指定了
RAILS_ENV,则不要建立与删除数据库。
7 Active Model
请参考 [Changelog][AM-CHANGELOG] 来了解更多细节。
7.1 弃用
- 弃用了
Validator#setup。现在要手动在 Validator 的 constructor 里处理。Commit
7.2 值得一提的变化
-
ActiveModel::Dirty加入新的 API:reset_changes与changes_applied,来控制改变的状态。
8 Active Support
请参考 Changelog 来了解更多细节。
8.1 移除
移除对
MultiJSONGem 的依赖。也就是说ActiveSupport::JSON.decode不再接受给MultiJSON的 hash 参数。PR#10576移除了
encode_jsonhook,本来可以用来把 object 转成 JSON。这个特性被抽成了 activesupport-json_encoder Gem,请参考 PR#12183 与这里。移除了
ActiveSupport::JSON::Variable。移除了
String#encoding_aware?(core_ext/string/encoding.rb)。移除了
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!请改用 Ruby 原生的Array#uniq与Array#uniq!。移除了
ActiveSupport::BasicObject请改用ActiveSupport::ProxyObject。移除了
BufferedLogger, 请改用ActiveSupport::Logger。移除了
assert_present与assert_blank,请改用assert object.blank?与assert object.present?。
8.2 弃用
弃用了
Numeric#{ago,until,since,from_now},要明确的将数值转成AS::Duration。比如5.ago请改成5.seconds.ago。 PR#12389引用路径里弃用了
active_support/core_ext/object/to_json. 请引用active_support/core_ext/object/json insteadPR#12203弃用了
ActiveSupport::JSON::Encoding::CircularReferenceError。 这个特性被抽成了 activesupport-json_encoder Gem,请参考 PR#12183 与这里。弃用了
ActiveSupport.encode_big_decimal_as_string选项。 这个特性被抽成了 activesupport-json_encoder Gem,请参考 PR#12183 与这里。
8.3 值得一提的变化
使用 JSON gem 重写 ActiveSupport 的 JSON 编码部分,提升了纯 Ruby 定制编码的效率。参考 PR#12183 与这里。
新增
ActiveSupport::Testing::TimeHelpers#travel与#travel_to。这两个方法通过 stubbingTime.now与Date.today,可设置任意时间,做时光旅行。参考 PR#12824新增
Numeric#in_milliseconds,像是 1 小时有几毫秒:1.hour.in_milliseconds。可以将时间转成毫秒,再传给 JavaScript 的getTime()函数。Commit新增了
Date#middle_of_day、DateTime#middle_of_day与Time#middle_of_day方法。同时添加了midday、noon、at_midday、at_noon、at_middle_of_day作为别名。PR#10879String#gsub(pattern,'')可简写为String#remove(pattern)。Commit移除了
'cow'=>'kine'这个不规则的转换。Commit
9 致谢
许多人花了宝贵的时间贡献至 Rails 项目,使 Rails 成为更稳定、更强韧的网络框架,参考完整的 Rails 贡献者清单,感谢所有的贡献者!
反馈
欢迎帮忙改善指南质量。
如发现任何错误,欢迎修正。开始贡献前,可先行阅读贡献指南:文档。
翻译如有错误,深感抱歉,欢迎 Fork 修正,或至此处回报。
文章可能有未完成或过时的内容。请先检查 Edge Guides 来确定问题在 master 是否已经修掉了。再上 master 补上缺少的文件。内容参考 Ruby on Rails 指南准则来了解行文风格。
最后,任何关于 Ruby on Rails 文档的讨论,欢迎到 rubyonrails-docs 邮件群组。