1 升級到 Rails 4.2
如果您正在升級現有應用程式,建議在進行升級之前先進行良好的測試覆蓋。如果尚未升級到 Rails 4.1,請先升級到該版本,然後確保應用程式運行正常,然後再嘗試升級到 Rails 4.2。在升級時要注意的事項列表可在指南 升級 Ruby on Rails 中找到。
2 主要功能
2.1 Active Job
Active Job 是 Rails 4.2 中的新框架。它是在排程系統(如 Resque、Delayed Job、Sidekiq 等)之上的通用介面。
使用 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 Basics 指南。
2.2 非同步郵件
在 Active Job 的基礎上,Action Mailer 現在提供了一個 deliver_later
方法,通過排程系統發送郵件,這樣即使排程系統是非同步的(默認的內聯排程系統是同步的),也不會阻塞控制器或模型。
仍然可以使用 deliver_now
立即發送郵件。
2.3 Adequate Record
Adequate Record 是 Active Record 中的一組性能改進,可以使常見的 find
和 find_by
調用以及某些關聯查詢速度提高最多 2 倍。
它通過將常見的 SQL 查詢緩存為預備語句並在類似調用上重複使用,跳過大部分的查詢生成工作。有關詳細信息,請參閱 Aaron Patterson 的博客文章。 Active Record會在支援的操作中自動利用這個功能,而不需要使用者參與或更改程式碼。以下是一些支援的操作範例:
Post.find(1) # 第一次呼叫會生成並緩存預備語句
Post.find(2) # 後續呼叫會重複使用緩存的預備語句
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)
需要強調的是,如上述範例所示,預備語句不會緩存方法呼叫中傳遞的值,而是為它們準備了佔位符。
以下情況不使用快取:
- 模型有預設範圍
- 模型使用單一表繼承
使用id列表的
find
,例如:# 不會被快取 Post.find(1, 2, 3) Post.find([1,2])
使用SQL片段的
find_by
:Post.find_by('published_at < ?', 2.weeks.ago)
2.4 Web Console
使用Rails 4.2生成的新應用程式現在預設附帶Web Console gem。Web Console在每個錯誤頁面上添加了一個互動式Ruby控制台,並提供了console
視圖和控制器幫助程式。
錯誤頁面上的互動式控制台允許您在異常發生的地方執行代碼。如果在視圖或控制器中的任何位置調用console
幫助程式,則在渲染完成後,將啟動具有最終上下文的互動式控制台。
2.5 外鍵支援
遷移DSL現在支援添加和刪除外鍵。它們也會被儲存到schema.rb
中。目前,只有mysql
,mysql2
和postgresql
適配器支援外鍵。
# 添加一個外鍵到`articles.author_id`,參照`authors.id`
add_foreign_key :articles, :authors
# 添加一個外鍵到`articles.author_id`,參照`users.lng_id`
add_foreign_key :articles, :users, column: :author_id, primary_key: "lng_id"
# 刪除`accounts.branch_id`上的外鍵
remove_foreign_key :accounts, :branches
# 刪除`accounts.owner_id`上的外鍵
remove_foreign_key :accounts, column: :owner_id
請參閱API文件中的add_foreign_key和remove_foreign_key以獲得詳細描述。
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。在你的Gemfile
中添加gem 'responders', '~> 2.0'
以使用它:
# 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:3000和http://localhost: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淨化器已經被一個基於Loofah和Nokogiri的新的、更強大、更靈活的實現所取代。新的淨化器更安全,其淨化功能更強大和靈活。
由於新的算法,對於某些極端輸入,淨化後的輸出可能會有所不同。
如果您對舊淨化器的精確輸出有特殊需求,可以將rails-deprecated_sanitizer gem添加到Gemfile
中,以獲得舊的行為。該gem不會發出棄用警告,因為它是選擇性的。
rails-deprecated_sanitizer
只支持Rails 4.2;對於Rails 5.0,將不再維護。
有關新淨化器的更多詳細信息,請參閱此博客文章。
3.6 assert_select
assert_select
現在基於Nokogiri。因此,一些以前有效的選擇器現在不再受支持。如果您的應用程序使用了這些拼寫,您需要對它們進行更新:
* 如果屬性選擇器中的值包含非字母數字字符,則可能需要對其進行引號引用。
```ruby
# 之前
a[href=/]
a[href$=/]
# 現在
a[href="/"]
a[href$="/"]
```
從包含無效HTML和不正確嵌套元素的HTML源代碼構建的DOM可能會有所不同。
例如:
# 內容: <div><i><p></i></div> # 之前: assert_select('div > i') # => true assert_select('div > p') # => false assert_select('i > p') # => true # 現在: assert_select('div > i') # => true assert_select('div > p') # => true assert_select('i > p') # => false
如果所選數據包含實體,則用於比較的選擇值以前是原始的(例如
AT&T
),現在是評估的(例如AT&T
)。# 內容: <p>AT&T</p> # 之前: assert_select('p', 'AT&T') # => true assert_select('p', 'AT&T') # => false # 現在: assert_select('p', 'AT&T') # => true assert_select('p', 'AT&T') # => false
此外,替換的語法已更改。
現在您必須使用:match
類似CSS的選擇器:
assert_select ":match('id', ?)", 'comment_1'
此外,當斷言失敗時,正則表達式替換的外觀不同。請注意,這裡的/hello/
:
assert_select(":match('id', ?)", /hello/)
變成了"(?-mix:hello)"
:
預期至少有1個匹配的元素 "div:match('id', "(?-mix:hello)")",但找到0個。
預期0大於等於1。
有關assert_select
的更多信息,請參見Rails Dom Testing文檔。
4 Railties
詳細更改請參閱[Changelog][railties]。
4.1 刪除
應用程序生成器中的
--skip-action-view
選項已被刪除。 (Pull Request)rails application
命令已被刪除,沒有替代品。 (Pull Request)
4.2 廢棄
對於生產環境,已廢棄缺失的
config.log_level
。 (Pull Request)廢棄
rake test:all
,改用rake test
,因為它現在運行test
文件夾中的所有測試。 (Pull Request)廢棄
rake test:all:db
,改用rake test:db
。 (Pull Request)廢棄
Rails::Rack::LogTailer
,沒有替代品。 (Commit)
4.3 重要更改
在默認應用程序
Gemfile
中引入了web-console
。 (Pull Request)為關聯引入了模型生成器的
required
選項。 (Pull Request)引入了
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
(Commit)
引入了
Rails::Application.config_for
,用於加載當前環境的配置。# config/exception_notification.yml production: url: http://127.0.0.1:8080 namespace: my_app_production development: url: http://localhost: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
。 (拉取請求)引入了一個 API 來註冊
rake notes
的新擴展。 (拉取請求)引入了
after_bundle
回調,用於 Rails 模板中使用。 (拉取請求)引入了
Rails.gem_version
作為一個方便的方法,返回Gem::Version.new(Rails.version)
。 (拉取請求)
5 Action Pack
詳細更改請參閱[變更日誌][action-pack]。
5.1 刪除項目
從 Rails 中刪除了
respond_with
和類級respond_to
,並將其移至responders
gem(版本2.0)。在你的Gemfile
中添加gem 'responders', '~> 2.0'
以繼續使用這些功能。 (拉取請求, 更多詳細資訊)刪除了已棄用的
AbstractController::Helpers::ClassMethods::MissingHelperError
,改用AbstractController::Helpers::MissingHelperError
。 (提交)
5.2 廢棄項目
廢棄了
*_path
助手函數的only_path
選項。 (提交)廢棄了
assert_tag
、assert_no_tag
、find_tag
和find_all_tag
,改用assert_select
。 (提交)廢棄了將路由器的
:to
選項設置為符號或不包含#
字符的字符串的支援:get '/posts', to: MyRackApp => (無需更改) get '/posts', to: 'post#index' => (無需更改) get '/posts', to: 'posts' => get '/posts', controller: :posts get '/posts', to: :index => get '/posts', action: :index
(提交)
廢棄了在 URL 助手函數中使用字符串鍵的支援:
# 不好的寫法 root_path('controller' => 'posts', 'action' => 'index') # 好的寫法 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 中刪除。render nothing: true
或渲染nil
內容不再在響應內容中添加單個空格填充。 (拉取請求)Rails 現在自動在 ETags 中包含模板的摘要。 (拉取請求)
傳遞給 URL 助手函數的片段現在會自動進行轉義。 (提交)
引入了
always_permitted_parameters
選項,用於配置全局允許的參數。該配置的默認值為['controller', 'action']
。 (拉取請求)*_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
詳細更改請參閱[更新日誌][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
特殊局部變量,用於與使用集合呈現的局部模板一起使用。它通過index
、size
、first?
和last?
方法提供對迭代的當前狀態的訪問。 (拉取請求)Placeholder I18n遵循與
label
I18n相同的慣例。 (拉取請求)
7 Action Mailer
詳細更改請參閱[更新日誌][action-mailer]。
7.1 廢棄
7.2 重要更改
在模板中,
link_to
和url_for
默認生成絕對URL,無需傳遞only_path: false
。 (提交)引入了
deliver_later
,它將一個作業排入應用程序的隊列,以異步方式發送電子郵件。 (拉取請求)新增了
show_previews
配置選項,用於在開發環境之外啟用郵件預覽功能。 (拉取請求)
8 Active Record
詳細更改請參閱[變更日誌][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_commit
和after_rollback
中吞噬錯誤的功能。 (拉取請求)廢棄了對
has_many :through
關聯自動檢測計數緩存的支援。現在應該手動在 通過記錄的has_many
和belongs_to
關聯上指定計數緩存。 (拉取請求)廢棄了將Active Record對象傳遞給
.find
或.exists?
的功能。請先調用對象的id
方法。 (提交 1, 2)廢棄了對於排除開始的PostgreSQL範圍值的支援。我們目前將PostgreSQL範圍映射為Ruby範圍。 這種轉換不完全可能,因為Ruby範圍不支援排除開始。
目前的解決方案是增加開始值,但這是不正確的,現在已被廢棄。對於我們不知道如何增加的子類型 (例如
succ
未定義)的範圍,將為具有排除開始的範圍引發ArgumentError
。 (提交)廢棄了在沒有連接的情況下調用
DatabaseTasks.load_schema
的功能。請改用DatabaseTasks.load_schema_current
。 (提交)廢棄了
sanitize_sql_hash_for_conditions
而沒有替代方法。使用Relation
執行查詢和更新是首選的API。 (提交)廢棄了不傳遞
null
選項的add_timestamps
和t.timestamps
。在Rails 5中,默認值null: true
將更改為null: false
。 (拉取請求)廢棄了不再需要的
Reflection#source_macro
方法,因為在Active Record中不再需要。 (拉取請求)廢棄了
serialized_attributes
而沒有替代方法。 (拉取請求)廢棄了在沒有列存在時從
column_for_attribute
返回nil
的功能。在Rails 5.0中,將返回一個空對象。 (拉取請求)廢棄了在關聯依賴於實例狀態的情況下(即使用接受參數的作用域定義的關聯)使用
.joins
、.preload
和.eager_load
的功能,而沒有替代方法。 (提交)
8.3 重要更改
SchemaDumper
在create_table
上使用了force: :cascade
。這使得在存在外鍵的情況下重新加載模式成為可能。為單數關聯添加了一個
required
選項,該選項在關聯上定義了存在驗證。 (拉取請求)ActiveRecord::Dirty
現在可以檢測到對可變值的原地更改。當未更改時,不再保存Active Record模型上的序列化屬性。 這也適用於其他類型,例如PostgreSQL上的字符串列和json列。 (拉取請求 1, 2, 3)引入了
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)添加了
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][active-model]。
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
方法,用於恢復已更改(dirty)的屬性到其先前的值。 (Pull Request 1, 2)has_secure_password
現在不再默認禁止空白密碼(即只包含空格的密碼)。 (Pull Request)如果啟用驗證,
has_secure_password
現在會驗證給定的密碼是否少於 72 個字符。 (Pull Request)
10 Active Support
詳細更改請參閱 Changelog。
10.1 刪除
刪除了已棄用的
Numeric#ago
、Numeric#until
、Numeric#since
、Numeric#from_now
方法。 (Commit)刪除了
ActiveSupport::Callbacks
的基於字符串的終止符的已棄用方法。 (Pull Request)
10.2 棄用
棄用
Kernel#silence_stderr
、Kernel#capture
和Kernel#quietly
方法,無替代方法。 (Pull Request)棄用
Class#superclass_delegating_accessor
,改用Class#class_attribute
。 (Pull Request)棄用
ActiveSupport::SafeBuffer#prepend!
,因為ActiveSupport::SafeBuffer#prepend
現在具有相同的功能。 (Pull Request)重要變更
引入了一個新的配置選項
active_support.test_order
,用於指定測試案例的執行順序。該選項目前的默認值為:sorted
,但在 Rails 5.0 中將更改為:random
。 (提交)travel_to
測試輔助方法現在將usec
組件截斷為 0。 (提交)Object#with_options
現在可以在區塊中不使用顯式接收器來使用。 (拉取請求)引入了
String#truncate_words
來按單詞數截斷字符串。 (拉取請求)添加了
Hash#transform_values
和Hash#transform_values!
,以簡化一個常見模式,其中哈希的值必須更改,但鍵保持不變。 (拉取請求)humanize
轉換器輔助方法現在會去除任何前導下劃線。 (提交)引入了
Concern#class_methods
作為module ClassMethods
的替代方案,以及Kernel#concern
來避免module Foo; extend ActiveSupport::Concern; end
的樣板代碼。 (提交)新增了關於常量自動加載和重新加載的指南。
11 貢獻者
請參閱完整的 Rails 貢獻者列表,感謝那些花了許多時間使 Rails 成為穩定且強大的框架的人。向他們致敬。
回饋
歡迎協助提升本指南的品質。
如果您發現任何錯別字或事實錯誤,請貢獻您的力量。 開始之前,您可以閱讀我們的 文件貢獻 部分。
您也可能會發現不完整的內容或過時的資訊。 請為主要的文件補充任何遺漏的內容。請先檢查 Edge 指南,以確認問題是否已經修復或尚未在主分支上修復。 請參考 Ruby on Rails 指南指引 以了解風格和慣例。
如果您發現需要修復但無法自行修補的問題,請 開啟一個問題。
最後但同樣重要的是,關於 Ruby on Rails 文件的任何討論都非常歡迎在 官方 Ruby on Rails 論壇 上進行。