1 一般建議
在嘗試升級現有應用程式之前,您應該確定自己有充分的理由進行升級。您需要權衡多個因素:對新功能的需求、尋找舊程式碼支援的難度增加,以及您可用的時間和技能,僅舉幾例。
1.1 測試覆蓋率
為了確保您的應用程式在升級後仍能正常運作,最好的方法是在開始升級流程之前就擁有良好的測試覆蓋率。如果您沒有自動化測試來驗證應用程式的大部分功能,您就需要花時間手動測試所有變更的部分。以 Rails 升級為例,這將意味著應用程式中的每一項功能都必須測試。為了您自己好,請在開始升級之前確保您的測試覆蓋率良好。
1.2 Ruby 版本
Rails 通常在發佈時會與最新發佈的 Ruby 版本保持接近。
- Rails 8.0 需要 Ruby 3.2.0 或更新版本。
- Rails 7.2 需要 Ruby 3.1.0 或更新版本。
- Rails 7.0 和 7.1 需要 Ruby 2.7.0 或更新版本。
- Rails 6 需要 Ruby 2.5.0 或更新版本。
- Rails 5 需要 Ruby 2.2.2 或更新版本。
最好將 Ruby 和 Rails 分開升級。先升級到您能使用的最新 Ruby 版本,然後再升級 Rails。
1.3 升級流程
在變更 Rails 版本時,最好一次移動一個小版本,以便充分利用棄用警告。Rails 版本號的格式為 Major.Minor.Patch。主要版本(Major)和小版本(Minor)允許對公共 API 進行變更,這可能會導致您的應用程式出現錯誤。修補版本(Patch)僅包含錯誤修復,不會變更任何公共 API。
升級流程應如下:
- 撰寫測試並確保測試通過。
- 移動到目前版本後的最新修補版本。
- 修復測試和已棄用的功能。
- 移動到下一個小版本的最新修補版本。
重複此流程,直到達到您的目標 Rails 版本。
1.3.1 版本之間的移動
要在版本之間移動:
- 變更
Gemfile
中的 Rails 版本號,並執行bundle update rails
。 - 如果執行 jsbundling-rails,請在
package.json
中變更 Rails JavaScript 套件的版本,並執行bin/rails javascript:install
。 - 執行更新任務。
- 執行您的測試。
您可以在這裡找到所有已發佈的 Rails gem 清單。
1.4 更新任務
Rails 提供 rails app:update
命令。在更新 Gemfile
中的 Rails 版本後,執行此命令。這將在互動式會話中幫助您建立新檔案並變更舊檔案。
$ bin/rails app:update
exist config
conflict config/application.rb
Overwrite /myapp/config/application.rb? (enter "h" for help) [Ynaqdh]
force config/application.rb
create config/initializers/new_framework_defaults_8_0.rb
...
別忘了檢查差異,看看是否有任何意外變更。請注意,在此過程中使用的 diff 和 merge 工具可以使用 THOR_DIFF
和 THOR_MERGE
環境變數來定義。
1.5 設定框架預設值
新的 Rails 版本可能具有與先前版本不同的組態預設值。但是,在遵循上述步驟之後,您的應用程式仍將以先前 Rails 版本的組態預設值執行。這是因為 config/application.rb
中的 config.load_defaults
的值尚未變更。
為了讓您能夠逐一升級到新的預設值,更新任務已建立一個檔案 config/initializers/new_framework_defaults_X.Y.rb
(檔案名稱中包含所需的 Rails 版本)。您應該透過取消註解檔案中的內容來啟用新的組態預設值;這可以在多次部署中逐步完成。一旦您的應用程式準備好使用新的預設值執行,您可以移除此檔案並切換 config.load_defaults
的值。
2 從 Rails 7.2 升級到 Rails 8.0
有關 Rails 8.0 所做變更的更多資訊,請參閱發行說明。
3 從 Rails 7.1 升級到 Rails 7.2
有關 Rails 7.2 所做變更的更多資訊,請參閱發行說明。
3.1 現在所有測試都遵守 active_job.queue_adapter
設定
如果您在 config/application.rb
或 config/environments/test.rb
檔案中設定了 config.active_job.queue_adapter
,您選擇的適配器先前並未在所有測試中一致地使用。在某些測試中會使用您的適配器,但在其他測試中則會使用 TestAdapter
。
在 Rails 7.2 中,如果提供了 queue_adapter
設定,所有測試都會遵守該設定。如果您將 queue_adapter
設定為 :test
以外的值,但撰寫的測試方式卻依賴於 TestAdapter
,這可能會導致測試錯誤。
如果未提供任何設定,則會繼續使用 TestAdapter
。
4 從 Rails 7.0 升級到 Rails 7.1
有關 Rails 7.1 所做變更的更多資訊,請參閱發行說明。
4.1 開發和測試環境的 secret_key_base 檔案已變更
在開發和測試環境中,Rails 從中讀取 secret_key_base
的檔案已從 tmp/development_secret.txt
重新命名為 tmp/local_secret.txt
。
您可以簡單地將先前的檔案重新命名為 local_secret.txt
以繼續使用相同的密鑰,或將密鑰從先前的檔案複製到新檔案。
如果沒有這樣做,Rails 會在應用程式載入時在新檔案 tmp/local_secret.txt
中產生新的密鑰。
這將使開發和測試環境中的所有現有會話/Cookie 無效,也會導致其他從 secret_key_base
衍生的簽章中斷,例如 Active Storage/Action Text 附件。
生產和其他環境不受影響。
4.2 自動載入的路徑不再位於 $LOAD_PATH 中
從 Rails 7.1 開始,自動載入器管理的目錄不再新增到 $LOAD_PATH
中。這表示無法使用手動 require
呼叫來載入其檔案,這無論如何都不應該這樣做。
減少 $LOAD_PATH
的大小可以加快未使用 bootsnap
的應用程式的 require
呼叫速度,並減少其他應用程式的 bootsnap
快取大小。
如果您希望這些路徑仍然位於 $LOAD_PATH
中,您可以選擇加入
config.add_autoload_paths_to_load_path = true
但不建議這樣做,自動載入路徑中的類別和模組應該要自動載入。也就是說,只需參考它們即可。
lib
目錄不受此旗標影響,它始終會新增到 $LOAD_PATH
中。
4.3 config.autoload_lib 和 config.autoload_lib_once
如果您的應用程式的自動載入或自動載入一次路徑中沒有 lib
,請跳過此章節。您可以透過檢查輸出來得知
# Print autoload paths.
$ bin/rails runner 'pp Rails.autoloaders.main.dirs'
# Print autoload once paths.
$ bin/rails runner 'pp Rails.autoloaders.once.dirs'
如果您的應用程式的自動載入路徑中已經有 lib
,通常在 config/application.rb
中會有類似以下的設定
# Autoload lib, but do not eager load it (maybe overlooked).
config.autoload_paths << config.root.join("lib")
或
# Autoload and also eager load lib.
config.autoload_paths << config.root.join("lib")
config.eager_load_paths << config.root.join("lib")
或
# Same, because all eager load paths become autoload paths too.
config.eager_load_paths << config.root.join("lib")
這仍然有效,但建議將這些行替換為更簡潔的
config.autoload_lib(ignore: %w(assets tasks))
請將任何其他不包含 .rb
檔案,或不應該重新載入或預先載入的 lib
子目錄新增到 ignore
清單中。例如,如果您的應用程式有 lib/templates
、lib/generators
或 lib/middleware
,您會新增相對於 lib
的名稱
config.autoload_lib(ignore: %w(assets tasks templates generators middleware))
透過這一行程式碼,如果 config.eager_load
為 true
(production
模式下的預設值),lib
中(未忽略的)程式碼也會預先載入。這通常是您想要的,但如果之前未將 lib
新增到預先載入路徑中,並且您仍然希望這樣做,請選擇退出
Rails.autoloaders.main.do_not_eager_load(config.root.join("lib"))
如果應用程式在 config.autoload_once_paths
中有 lib
,則 config.autoload_lib_once
方法與之類似。
4.4 ActiveStorage::BaseController
不再包含串流關注點
繼承自 ActiveStorage::BaseController
並使用串流來實作自訂檔案服務邏輯的應用程式控制器現在必須明確包含 ActiveStorage::Streaming
模組。
4.5 MemCacheStore
和 RedisCacheStore
現在預設使用連線池
connection_pool
gem 已新增為 activesupport
gem 的依賴項,MemCacheStore
和 RedisCacheStore
現在預設使用連線池。
如果您不想使用連線池,請在設定快取儲存時將 :pool
選項設定為 false
config.cache_store = :mem_cache_store, "cache.example.com", { pool: false }
如需更多資訊,請參閱使用 Rails 快取指南。
4.6 SQLite3Adapter
現在已設定為以嚴格字串模式使用
使用嚴格字串模式會停用雙引號字串文字。
SQLite 對雙引號字串文字有一些怪癖。它首先嘗試將雙引號字串視為識別碼名稱,但如果它們不存在,則會將它們視為字串文字。因此,錯誤可能會在不知不覺中發生。例如,可以為不存在的欄建立索引。有關更多詳細資訊,請參閱 SQLite 文件。
如果您不想以嚴格模式使用 SQLite3Adapter
,您可以停用此行為
# config/application.rb
config.active_record.sqlite3_adapter_strict_strings_by_default = false
4.7 支援 ActionMailer::Preview
的多個預覽路徑
選項 config.action_mailer.preview_path
已棄用,改用 config.action_mailer.preview_paths
。將路徑附加到此設定選項會導致在搜尋郵件程式預覽時使用這些路徑。
config.action_mailer.preview_paths << "#{Rails.root}/lib/mailer_previews"
4.8 config.i18n.raise_on_missing_translations = true
現在會在任何遺失的翻譯上引發錯誤。
先前,它只會在視圖或控制器中呼叫時引發錯誤。現在,只要 I18n.t
收到無法識別的索引鍵時,就會引發錯誤。
# with config.i18n.raise_on_missing_translations = true
# in a view or controller:
t("missing.key") # raises in 7.0, raises in 7.1
I18n.t("missing.key") # didn't raise in 7.0, raises in 7.1
# anywhere:
I18n.t("missing.key") # didn't raise in 7.0, raises in 7.1
如果您不希望這種行為,您可以設定 config.i18n.raise_on_missing_translations = false
# with config.i18n.raise_on_missing_translations = false
# in a view or controller:
t("missing.key") # didn't raise in 7.0, doesn't raise in 7.1
I18n.t("missing.key") # didn't raise in 7.0, doesn't raise in 7.1
# anywhere:
I18n.t("missing.key") # didn't raise in 7.0, doesn't raise in 7.1
或者,您可以自訂 I18n.exception_handler
。如需更多資訊,請參閱 i18n 指南。
AbstractController::Translation.raise_on_missing_translations
已移除。這是一個私有 API,如果您依賴它,您應該遷移到 config.i18n.raise_on_missing_translations
或自訂的例外處理程式。
4.9 bin/rails test
現在會執行 test:prepare
任務
當透過 bin/rails test
執行測試時,rake test:prepare
任務會在測試執行前執行。如果您增強了 test:prepare
任務,您的增強功能會在您的測試之前執行。tailwindcss-rails
、jsbundling-rails
和 cssbundling-rails
都會增強此任務,其他第三方 gem 也會。
請參閱測試 Rails 應用程式指南以獲取更多資訊。
如果您執行單一檔案的測試 (bin/rails test test/models/user_test.rb
),test:prepare
將不會在其之前執行。
4.10 從 @rails/ujs
匯入語法已修改
從 Rails 7.1 開始,從 @rails/ujs
匯入模組的語法已修改。Rails 不再支援直接從 @rails/ujs
匯入模組。
例如,嘗試從該函式庫匯入函式將會失敗
import { fileInputSelector } from "@rails/ujs"
// ERROR: export 'fileInputSelector' (imported as 'fileInputSelector') was not found in '@rails/ujs' (possible exports: default)
在 Rails 7.1 中,使用者應該先直接從 @rails/ujs
匯入 Rails 物件。然後,使用者可以從 Rails 物件匯入特定的模組。
以下顯示 Rails 7.1 中的匯入範例
import Rails from "@rails/ujs"
// Alias the method
const fileInputSelector = Rails.fileInputSelector
// Alternatively, reference it from the Rails object where it is used
Rails.fileInputSelector(...)
4.11 Rails.logger
現在會回傳 ActiveSupport::BroadcastLogger
實例
ActiveSupport::BroadcastLogger
類別是一個新的記錄器,可以輕鬆地將日誌廣播到不同的接收器 (STDOUT、日誌檔案...)。
廣播日誌的 API (使用 ActiveSupport::Logger.broadcast
方法) 已移除,且先前為私有的。如果您的應用程式或函式庫依賴此 API,您需要進行以下變更
logger = Logger.new("some_file.log")
# Before
Rails.logger.extend(ActiveSupport::Logger.broadcast(logger))
# After
Rails.logger.broadcast_to(logger)
如果您的應用程式已設定自訂記錄器,Rails.logger
會將所有方法包裝並代理給它。您的部分不需要變更即可使其運作。
如果您需要存取您的自訂記錄器實例,您可以使用 broadcasts
方法來執行此操作
# config/application.rb
config.logger = MyLogger.new
# Anywhere in your application
puts Rails.logger.class #=> BroadcastLogger
puts Rails.logger.broadcasts #=> [MyLogger]
4.12 Active Record 加密演算法變更
Active Record 加密現在使用 SHA-256 作為其雜湊摘要演算法。如果您有使用先前 Rails 版本加密的資料,則需要考慮兩種情況
如果您將
config.active_support.key_generator_hash_digest_class
設定為 SHA-1 (Rails 7.0 之前的預設值),您也需要為 Active Record 加密設定 SHA-1config.active_record.encryption.hash_digest_class = OpenSSL::Digest::SHA1
如果您將
config.active_support.key_generator_hash_digest_class
設定為 SHA-256 (7.0 中的新預設值),則您需要為 Active Record 加密設定 SHA-256config.active_record.encryption.hash_digest_class = OpenSSL::Digest::SHA256
請參閱設定 Rails 應用程式指南,以獲取有關 config.active_record.encryption.hash_digest_class
的更多資訊。
此外,還引入了一個新的設定config.active_record.encryption.support_sha1_for_non_deterministic_encryption
來解決 一個錯誤,該錯誤導致某些屬性即使透過上述 hash_digest_class
設定配置了 SHA-256,也會使用 SHA-1 進行加密。
預設情況下,config.active_record.encryption.support_sha1_for_non_deterministic_encryption
在 Rails 7.1 中已停用。如果您擁有在 Rails < 7.1 版本中加密的資料,並且您認為可能受到上述錯誤的影響,則應啟用此設定
config.active_record.encryption.support_sha1_for_non_deterministic_encryption = true
如果您正在使用加密資料,請仔細查看以上內容。
4.13 在 Controller 測試、整合測試和系統測試中處理異常的新方法
config.action_dispatch.show_exceptions
設定控制 Action Pack 如何處理回應請求時引發的異常。
在 Rails 7.1 之前,設定 config.action_dispatch.show_exceptions = true
會設定 Action Pack 來救援異常並呈現適當的 HTML 錯誤頁面,例如使用 404 Not found
狀態碼呈現 public/404.html
而不是引發 ActiveRecord::RecordNotFound
異常。設定 config.action_dispatch.show_exceptions = false
會設定 Action Pack 來不救援異常。在 Rails 7.1 之前,新應用程式會使用 config/environments/test.rb
中的一行程式碼來設定 config.action_dispatch.show_exceptions = false
。
Rails 7.1 將可接受的值從 true
和 false
變更為 :all
、:rescuable
和 :none
。
:all
- 針對所有異常呈現 HTML 錯誤頁面 (相當於true
):rescuable
- 針對config.action_dispatch.rescue_responses
宣告的異常呈現 HTML 錯誤頁面:none
(相當於false
) - 不救援任何異常
由 Rails 7.1 或更新版本產生的應用程式會在它們的 config/environments/test.rb
中設定 config.action_dispatch.show_exceptions = :rescuable
。升級時,現有的應用程式可以將 config.action_dispatch.show_exceptions = :rescuable
變更為使用新的行為,或將舊的值替換為對應的新值 (true
替換 :all
,false
替換 :none
)。
5 從 Rails 6.1 升級到 Rails 7.0
有關對 Rails 7.0 所做的變更的更多資訊,請參閱發行說明。
5.1 ActionView::Helpers::UrlHelper#button_to
行為已變更
從 Rails 7.0 開始,如果使用持續性的 Active Record 物件來建立按鈕 URL,button_to
會呈現具有 patch
HTTP 動詞的 form
標籤。為了保持目前行為,請考慮明確傳遞 method:
選項
-button_to("Do a POST", [:my_custom_post_action_on_workshop, Workshop.find(1)])
+button_to("Do a POST", [:my_custom_post_action_on_workshop, Workshop.find(1)], method: :post)
或使用輔助方法來建立 URL
-button_to("Do a POST", [:my_custom_post_action_on_workshop, Workshop.find(1)])
+button_to("Do a POST", my_custom_post_action_on_workshop_workshop_path(Workshop.find(1)))
5.2 Spring
如果您的應用程式使用 Spring,則需要將其升級到至少 3.0.0 版本。否則,您會收到
undefined method `mechanism=' for ActiveSupport::Dependencies:Module
此外,請確保 config.cache_classes
在 config/environments/test.rb
中設定為 false
。
5.3 Sprockets 現在是可選的相依性
gem rails
不再依賴 sprockets-rails
。如果您的應用程式仍然需要使用 Sprockets,請務必將 sprockets-rails
新增至您的 Gemfile。
gem "sprockets-rails"
5.4 應用程式需要在 zeitwerk
模式下執行
仍然在 classic
模式下執行的應用程式必須切換到 zeitwerk
模式。請查看 Classic to Zeitwerk HOWTO 指南以獲取詳細資訊。
5.5 setter config.autoloader=
已刪除
在 Rails 7 中,沒有設定自動載入模式的設定點,config.autoloader=
已刪除。如果您出於任何原因將其設定為 :zeitwerk
,請將其移除。
5.6 ActiveSupport::Dependencies
私有 API 已刪除
ActiveSupport::Dependencies
的私有 API 已刪除。這包括像 hook!
、unhook!
、depend_on
、require_or_load
、mechanism
和許多其他方法。
以下是一些重點
- 如果您使用
ActiveSupport::Dependencies.constantize
或ActiveSupport::Dependencies.safe_constantize
,只需將其變更為String#constantize
或String#safe_constantize
。
ActiveSupport::Dependencies.constantize("User") # NO LONGER POSSIBLE
"User".constantize # 👍
對
ActiveSupport::Dependencies.mechanism
的任何使用 (讀取器或寫入器) 都必須透過存取config.cache_classes
來相應地取代。如果您想追蹤自動載入器的活動,
ActiveSupport::Dependencies.verbose=
不再可用,只需在config/application.rb
中抛出Rails.autoloaders.log!
。
輔助內部類別或模組也已消失,例如 ActiveSupport::Dependencies::Reference
、ActiveSupport::Dependencies::Blamable
和其他。
5.7 初始化期間的自動載入
在 to_prepare
區塊之外,在初始化期間自動載入可重新載入常數的應用程式,會卸載這些常數,並且自 Rails 6.0 以來會發出此警告
DEPRECATION WARNING: Initialization autoloaded the constant ....
Being able to do this is deprecated. Autoloading during initialization is going
to be an error condition in future versions of Rails.
...
如果您仍然在日誌中收到此警告,請查看 自動載入指南中關於應用程式啟動時自動載入的部分。否則,您會在 Rails 7 中收到 NameError
。
由 once
自動載入器管理的常數可以在初始化期間自動載入,並且它們可以正常使用,不需要 to_prepare
區塊。但是,現在會更早設定 once
自動載入器以支援此功能。如果應用程式有自訂的 inflections,並且 once
自動載入器應該知道它們,則您需要將 config/initializers/inflections.rb
中的程式碼移至 config/application.rb
中應用程式類別定義的主體中
module MyApp
class Application < Rails::Application
# ...
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.acronym "HTML"
end
end
end
5.8 設定 config.autoload_once_paths
的能力
config.autoload_once_paths
可以設定在 config/application.rb
中定義的應用程式類別的主體中,或設定在 config/environments/*
中環境的設定中。
同樣地,引擎可以在引擎類別的主體中或環境的設定中設定該集合。
在那之後,該集合會被凍結,您可以從那些路徑自動載入。特別是,您可以在初始化期間從那裡自動載入。它們由 Rails.autoloaders.once
自動載入器管理,該自動載入器不重新載入,僅自動載入/急切載入。
如果您在處理環境設定之後設定此設定,並且收到 FrozenError
,請移動程式碼。
5.9 ActionDispatch::Request#content_type
現在會傳回 Content-Type 標頭,如同它本身。
先前,ActionDispatch::Request#content_type
傳回的值不包含字元集部分。此行為已變更為傳回包含字元集部分的 Content-Type 標頭,如同它本身。
如果您只想要 MIME 類型,請改用 ActionDispatch::Request#media_type
。
之前
request = ActionDispatch::Request.new("CONTENT_TYPE" => "text/csv; header=present; charset=utf-16", "REQUEST_METHOD" => "GET")
request.content_type #=> "text/csv"
之後
request = ActionDispatch::Request.new("Content-Type" => "text/csv; header=present; charset=utf-16", "REQUEST_METHOD" => "GET")
request.content_type #=> "text/csv; header=present; charset=utf-16"
request.media_type #=> "text/csv"
5.10 金鑰產生器摘要類別變更需要 Cookie 輪換器
金鑰產生器的預設摘要類別正從 SHA1 變更為 SHA256。這會對 Rails 產生的任何加密訊息產生影響,包括加密的 Cookie。
為了能夠讀取使用舊摘要類別的訊息,必須註冊輪換器。未能這樣做可能會導致使用者在升級期間的會話失效。
以下是加密和簽署的 Cookie 的輪換器範例。
# config/initializers/cookie_rotator.rb
Rails.application.config.after_initialize do
Rails.application.config.action_dispatch.cookies_rotations.tap do |cookies|
authenticated_encrypted_cookie_salt = Rails.application.config.action_dispatch.authenticated_encrypted_cookie_salt
signed_cookie_salt = Rails.application.config.action_dispatch.signed_cookie_salt
secret_key_base = Rails.application.secret_key_base
key_generator = ActiveSupport::KeyGenerator.new(
secret_key_base, iterations: 1000, hash_digest_class: OpenSSL::Digest::SHA1
)
key_len = ActiveSupport::MessageEncryptor.key_len
old_encrypted_secret = key_generator.generate_key(authenticated_encrypted_cookie_salt, key_len)
old_signed_secret = key_generator.generate_key(signed_cookie_salt)
cookies.rotate :encrypted, old_encrypted_secret
cookies.rotate :signed, old_signed_secret
end
end
5.11 ActiveSupport::Digest 的摘要類別變更為 SHA256
ActiveSupport::Digest 的預設摘要類別正從 SHA1 變更為 SHA256。這會對諸如 Etag 之類的事物產生影響,這些事物會變更和快取金鑰也是如此。變更這些金鑰可能會影響快取命中率,因此在升級到新的雜湊時,請小心並留意這一點。
5.12 新的 ActiveSupport::Cache 序列化格式
引入了更快、更精簡的序列化格式。
要啟用它,您必須設定 config.active_support.cache_format_version = 7.0
# config/application.rb
config.load_defaults 6.1
config.active_support.cache_format_version = 7.0
或簡單地
# config/application.rb
config.load_defaults 7.0
然而,Rails 6.1 應用程式無法讀取這種新的序列化格式,因此為了確保無縫升級,您必須先使用 config.active_support.cache_format_version = 6.1
部署 Rails 7.0 的升級,然後只有在所有 Rails 程序都更新後,才能設定 config.active_support.cache_format_version = 7.0
。
Rails 7.0 可以讀取兩種格式,因此在升級期間快取不會失效。
5.13 Active Storage 影片預覽圖片生成
影片預覽圖片生成現在使用 FFmpeg 的場景變更偵測來產生更有意義的預覽圖片。先前會使用影片的第一個影格,如果影片從黑色淡入,就會造成問題。此變更需要 FFmpeg v3.4 以上版本。
5.14 Active Storage 預設變體處理器變更為 :vips
對於新的應用程式,圖片轉換將使用 libvips 而不是 ImageMagick。這將減少產生變體所需的時間,以及 CPU 和記憶體使用量,從而提高依賴 Active Storage 提供圖片的應用程式的回應時間。
:mini_magick
選項並未被棄用,因此可以繼續使用。
若要將現有的應用程式遷移到 libvips,請設定
Rails.application.config.active_storage.variant_processor = :vips
然後您需要將現有的圖片轉換程式碼變更為 image_processing
巨集,並將 ImageMagick 的選項替換為 libvips 的選項。
5.14.1 將 resize 替換為 resize_to_limit
- variant(resize: "100x")
+ variant(resize_to_limit: [100, nil])
如果您不這樣做,當您切換到 vips 時,您會看到這個錯誤:no implicit conversion to float from string
。
5.14.2 裁切時使用陣列
- variant(crop: "1920x1080+0+0")
+ variant(crop: [0, 0, 1920, 1080])
如果您在遷移到 vips 時不這樣做,您會看到以下錯誤:unable to call crop: you supplied 2 arguments, but operation needs 5
。
5.14.3 限制您的裁切值
Vips 在裁切方面比 ImageMagick 更嚴格
- 如果
x
和/或y
是負值,它將不會裁切。例如:[-10, -10, 100, 100]
- 如果位置 (
x
或y
) 加上裁切尺寸 (width
、height
) 大於圖片,它將不會裁切。例如:一張 125x125 的圖片和一個[50, 50, 100, 100]
的裁切。
如果您在遷移到 vips 時不這樣做,您會看到以下錯誤:extract_area: bad extract area
5.14.4 調整 resize_and_pad
使用的背景顏色
Vips 使用黑色作為 resize_and_pad
的預設背景顏色,而不是像 ImageMagick 一樣使用白色。請使用 background
選項來修正此問題
- variant(resize_and_pad: [300, 300])
+ variant(resize_and_pad: [300, 300, background: [255]])
5.14.5 移除任何基於 EXIF 的旋轉
Vips 在處理變體時會使用 EXIF 值自動旋轉圖片。如果您先前儲存了使用者上傳照片的旋轉值,以便使用 ImageMagick 應用旋轉,您必須停止這樣做
- variant(format: :jpg, rotate: rotation_value)
+ variant(format: :jpg)
5.14.6 將 monochrome 替換為 colourspace
Vips 使用不同的選項來製作單色圖片
- variant(monochrome: true)
+ variant(colourspace: "b-w")
5.14.7 切換到 libvips 選項以壓縮圖片
JPEG
- variant(strip: true, quality: 80, interlace: "JPEG", sampling_factor: "4:2:0", colorspace: "sRGB")
+ variant(saver: { strip: true, quality: 80, interlace: true })
PNG
- variant(strip: true, quality: 75)
+ variant(saver: { strip: true, compression: 9 })
WEBP
- variant(strip: true, quality: 75, define: { webp: { lossless: false, alpha_quality: 85, thread_level: 1 } })
+ variant(saver: { strip: true, quality: 75, lossless: false, alpha_q: 85, reduction_effort: 6, smart_subsample: true })
GIF
- variant(layers: "Optimize")
+ variant(saver: { optimize_gif_frames: true, optimize_gif_transparency: true })
5.14.8 部署到生產環境
Active Storage 會將必須執行的轉換列表編碼到圖片的網址中。如果您的應用程式快取了這些網址,當您將新程式碼部署到生產環境後,您的圖片將會損壞。因此,您必須手動使受影響的快取鍵失效。
例如,如果您在視圖中有類似這樣的程式碼
<% @products.each do |product| %>
<% cache product do %>
<%= image_tag product.cover_photo.variant(resize: "200x") %>
<% end %>
<% end %>
您可以透過觸摸產品或變更快取鍵來使快取失效
<% @products.each do |product| %>
<% cache ["v2", product] do %>
<%= image_tag product.cover_photo.variant(resize_to_limit: [200, nil]) %>
<% end %>
<% end %>
5.15 Rails 版本現在包含在 Active Record 綱要傾印中
Rails 7.0 變更了一些欄位類型的預設值。為了避免從 6.1 升級到 7.0 的應用程式使用新的 7.0 預設值載入目前的綱要,Rails 現在會在綱要傾印中包含框架的版本。
在 Rails 7.0 中首次載入綱要之前,請務必執行 rails app:update
,以確保綱要的版本包含在綱要傾印中。
綱要檔案將如下所示
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# This file is the source Rails uses to define your schema when running `bin/rails
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
# be faster and is potentially less error prone than running all of your
# migrations from scratch. Old migrations may fail to apply correctly if those
# migrations use external dependencies or application code.
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[6.1].define(version: 2022_01_28_123512) do
# ...
end
當您第一次使用 Rails 7.0 傾印綱要時,您會看到該檔案的許多變更,包括一些欄位資訊。請務必檢閱新的綱要檔案內容並將其提交到您的儲存庫。
6 從 Rails 6.0 升級到 Rails 6.1
有關 Rails 6.1 所做變更的更多資訊,請參閱發行說明。
6.1 Rails.application.config_for
的傳回值不再支援使用字串索引鍵存取。
假設有類似這樣的設定檔
# config/example.yml
development:
options:
key: value
Rails.application.config_for(:example).options
這先前會傳回一個雜湊,您可以使用字串索引鍵存取值。這在 6.0 中已棄用,現在已不再有效。
如果您仍然想要使用字串索引鍵存取值,您可以對 config_for
的傳回值呼叫 with_indifferent_access
,例如
Rails.application.config_for(:example).with_indifferent_access.dig("options", "key")
6.2 使用 respond_to#any
時,回應的 Content-Type
回應中傳回的 Content-Type 標頭可能與 Rails 6.0 傳回的不同,更具體地說,如果您的應用程式使用 respond_to { |format| format.any }
。Content-Type 現在將基於給定的區塊,而不是請求的格式。
範例
def my_action
respond_to do |format|
format.any { render(json: { foo: "bar" }) }
end
end
get("my_action.csv")
先前的行為是傳回 text/csv
回應的 Content-Type,這是不準確的,因為正在呈現 JSON 回應。目前的行為會正確傳回 application/json
回應的 Content-Type。
如果您的應用程式依賴先前的錯誤行為,建議您指定您的動作接受哪些格式,即
format.any(:xml, :json) { render request.format.to_sym => @people }
6.3 ActiveSupport::Callbacks#halted_callback_hook
現在會接收第二個引數
Active Support 允許您在回呼停止鏈時覆寫 halted_callback_hook
。此方法現在會接收第二個引數,即正在停止的回呼名稱。如果您有類別覆寫此方法,請確保它接受兩個引數。請注意,這是一項重大變更,沒有先前的棄用週期(為了效能考量)。
範例
class Book < ApplicationRecord
before_save { throw(:abort) }
before_create { throw(:abort) }
def halted_callback_hook(filter, callback_name) # => This method now accepts 2 arguments instead of 1
Rails.logger.info("Book couldn't be #{callback_name}d")
end
end
6.4 控制器中的 helper
類別方法使用 String#constantize
從概念上講,在 Rails 6.1 之前
helper "foo/bar"
導致
require_dependency "foo/bar_helper"
module_name = "foo/bar_helper".camelize
module_name.constantize
現在它會這樣做
prefix = "foo/bar".camelize
"#{prefix}Helper".constantize
此變更與大多數應用程式向後相容,在這種情況下,您不需要執行任何操作。
但是,從技術上講,控制器可以將 helpers_path
設定為指向 $LOAD_PATH
中不在自動載入路徑中的目錄。不再直接支援這種使用案例。如果 helper 模組不是可自動載入的,則應用程式負責在呼叫 helper
之前載入它。
6.5 從 HTTP 重新導向到 HTTPS 現在將使用 308 HTTP 狀態碼
當將非 GET/HEAD 請求從 HTTP 重新導向到 HTTPS 時,ActionDispatch::SSL
中使用的預設 HTTP 狀態碼已變更為 308
,如 https://tools.ietf.org/html/rfc7538 中所定義。
6.6 Active Storage 現在需要 Image Processing
在 Active Storage 中處理變體時,現在必須捆綁 image_processing gem,而不是直接使用 mini_magick
。預設情況下,Image Processing 已設定為在幕後使用 mini_magick
,因此最簡單的升級方式是將 mini_magick
gem 替換為 image_processing
gem,並確保移除對 combine_options
的明確使用,因為不再需要它。
為了提高可讀性,您可能希望將原始的 resize
呼叫變更為 image_processing
巨集。例如,不要使用
video.preview(resize: "100x100")
video.preview(resize: "100x100>")
video.preview(resize: "100x100^")
您可以分別執行
video.preview(resize_to_fit: [100, 100])
video.preview(resize_to_limit: [100, 100])
video.preview(resize_to_fill: [100, 100])
6.7 新的 ActiveModel::Error
類別
錯誤現在是新的 ActiveModel::Error
類別的實例,並變更了 API。這些變更中的一些變更可能會根據您操作錯誤的方式擲回錯誤,而其他變更則會列印棄用警告,以便在 Rails 7.0 中修正。
有關此變更的更多資訊和有關 API 變更的詳細資訊,請參閱此 PR。
7 從 Rails 5.2 升級到 Rails 6.0
有關 Rails 6.0 所做變更的更多資訊,請參閱發行說明。
7.1 使用 Webpacker
Webpacker 是 Rails 6 的預設 JavaScript 編譯器。但是,如果您正在升級應用程式,則預設情況下不會啟用它。如果您想要使用 Webpacker,請將其包含在您的 Gemfile 中並安裝它
gem "webpacker"
$ bin/rails webpacker:install
7.2 強制 SSL
控制器上的 force_ssl
方法已棄用,將在 Rails 6.1 中移除。建議您啟用 config.force_ssl
,以在您的應用程式中強制執行 HTTPS 連線。如果您需要從重新導向中豁免特定端點,您可以使用 config.ssl_options
來設定該行為。
7.3 目的和到期中繼資料現在會內嵌到已簽署和加密的 Cookie 中,以提高安全性
為了提高安全性,Rails 會將目的和到期中繼資料內嵌到加密或已簽署的 Cookie 值中。
然後,Rails 可以阻止嘗試複製 Cookie 的已簽署/加密值並將其用作另一個 Cookie 值的攻擊。
這種新的內嵌中繼資料使這些 Cookie 與 Rails 6.0 之前的版本不相容。
如果您需要讓 Rails 5.2 和更舊的版本讀取您的 Cookie,或者您仍在驗證您的 6.0 部署並且想要能夠回滾,請將 Rails.application.config.action_dispatch.use_cookies_with_metadata
設定為 false
。
7.4 所有 npm 套件都已移至 @rails
範圍
如果您先前透過 npm/yarn 載入任何 actioncable
、activestorage
或 rails-ujs
套件,您必須更新這些相依性的名稱,才能將它們升級到 6.0.0
actioncable → @rails/actioncable
activestorage → @rails/activestorage
rails-ujs → @rails/ujs
7.5 Action Cable JavaScript API 變更
Action Cable JavaScript 套件已從 CoffeeScript 轉換為 ES2015,我們現在會在 npm 發行版中發布原始程式碼。
此版本包含 Action Cable JavaScript API 可選部分的重大變更
WebSocket 配接器和記錄器配接器的設定已從
ActionCable
的屬性移至ActionCable.adapters
的屬性。如果您正在設定這些配接器,您需要進行這些變更- ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket
- ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger
ActionCable.startDebugging()
和ActionCable.stopDebugging()
方法已移除,並替換為屬性ActionCable.logger.enabled
。如果您正在使用這些方法,您需要進行這些變更- ActionCable.startDebugging() + ActionCable.logger.enabled = true
- ActionCable.stopDebugging() + ActionCable.logger.enabled = false
7.6 ActionDispatch::Response#content_type
現在會傳回未修改的 Content-Type 標頭
先前,ActionDispatch::Response#content_type
的傳回值不包含 charset 部分。此行為已變更為也包含先前省略的 charset 部分。
如果您只需要 MIME 類型,請改用 ActionDispatch::Response#media_type
。
之前
resp = ActionDispatch::Response.new(200, "Content-Type" => "text/csv; header=present; charset=utf-16")
resp.content_type #=> "text/csv; header=present"
之後
resp = ActionDispatch::Response.new(200, "Content-Type" => "text/csv; header=present; charset=utf-16")
resp.content_type #=> "text/csv; header=present; charset=utf-16"
resp.media_type #=> "text/csv"
7.7 新的 config.hosts
設定
Rails 現在有一個新的 config.hosts
設定,用於安全目的。此設定在開發中預設為 localhost
。如果您在開發中使用其他網域,您需要像這樣允許它們
# config/environments/development.rb
config.hosts << "dev.myapp.com"
config.hosts << /[a-z0-9-]+\.myapp\.com/ # Optionally, regexp is allowed as well
對於其他環境,config.hosts
預設為空,這表示 Rails 完全不會驗證主機。您可以選擇性地新增它們,如果您想要在生產環境中驗證它。
7.8 自動載入
Rails 6 的預設設定
# config/application.rb
config.load_defaults 6.0
在 CRuby 上啟用 zeitwerk
自動載入模式。在該模式下,自動載入、重新載入和急切載入由 Zeitwerk 管理。
如果您正在使用先前 Rails 版本的預設值,您可以像這樣啟用 zeitwerk
# config/application.rb
config.autoloader = :zeitwerk
7.8.1 公開 API
一般而言,應用程式不需要直接使用 Zeitwerk 的 API。Rails 會根據現有的合約設定所有內容:config.autoload_paths
、config.cache_classes
等。
雖然應用程式應該堅持使用該介面,但實際的 Zeitwerk 載入器物件可以像這樣存取
Rails.autoloaders.main
例如,如果您需要預先載入單表繼承 (STI) 類別或設定自訂 inflector,這可能會很方便。
7.8.2 專案結構
如果正在升級的應用程式正確自動載入,則專案結構應已大部分相容。
然而,classic
模式會從遺失的常數名稱(underscore
)推斷檔案名稱,而 zeitwerk
模式則會從檔案名稱推斷常數名稱(camelize
)。這些輔助方法並不總是互為反函數,尤其是在涉及縮寫時。例如,"FOO".underscore
是 "foo"
,但 "foo".camelize
是 "Foo"
,而不是 "FOO"
。
可以使用 zeitwerk:check
任務檢查相容性
$ bin/rails zeitwerk:check
Hold on, I am eager loading the application.
All is good!
7.8.3 require_dependency
所有已知的 require_dependency
使用案例都已消除,您應該在專案中搜尋並刪除它們。
如果您的應用程式使用單表繼承,請參閱「自動載入和重新載入常數(Zeitwerk 模式)」指南中的 單表繼承章節。
7.8.4 類別和模組定義中的完整名稱
您現在可以在類別和模組定義中可靠地使用常數路徑
# Autoloading in this class' body matches Ruby semantics now.
class Admin::UsersController < ApplicationController
# ...
end
需要注意的一個小陷阱是,根據執行順序,經典的自動載入器有時能夠在以下程式碼中自動載入 Foo::Wadus
class Foo::Bar
Wadus
end
這與 Ruby 的語義不符,因為 Foo
不在巢狀結構中,而且在 zeitwerk
模式下完全無法運作。如果您發現這種邊緣案例,可以使用完整名稱 Foo::Wadus
class Foo::Bar
Foo::Wadus
end
或將 Foo
加入巢狀結構
module Foo
class Bar
Wadus
end
end
7.8.5 Concerns
您可以從標準結構自動載入和預先載入,例如
app/models
app/models/concerns
在這種情況下,app/models/concerns
被假設為根目錄(因為它屬於自動載入路徑),並且它會被忽略為命名空間。因此,app/models/concerns/foo.rb
應該定義 Foo
,而不是 Concerns::Foo
。
Concerns::
命名空間在經典的自動載入器中作為實作的副作用而運作,但它並非真正的預期行為。使用 Concerns::
的應用程式需要重新命名這些類別和模組,才能在 zeitwerk
模式下執行。
7.8.6 在自動載入路徑中包含 app
某些專案希望像 app/api/base.rb
定義 API::Base
,並將 app
加入自動載入路徑,以便在 classic
模式下完成此操作。由於 Rails 會自動將 app
的所有子目錄加入自動載入路徑,因此我們遇到了另一個巢狀根目錄的情況,因此該設定不再有效。這與我們上面解釋的 concerns
原則類似。
如果您想保留該結構,您需要在初始化器中從自動載入路徑中刪除該子目錄
ActiveSupport::Dependencies.autoload_paths.delete("#{Rails.root}/app/api")
7.8.7 自動載入的常數和明確的命名空間
如果命名空間定義在檔案中,如這裡的 Hotel
app/models/hotel.rb # Defines Hotel.
app/models/hotel/pricing.rb # Defines Hotel::Pricing.
則必須使用 class
或 module
關鍵字設定 Hotel
常數。例如
class Hotel
end
很好。
類似的替代方案
Hotel = Class.new
或
Hotel = Struct.new
將無法運作,找不到 Hotel::Pricing
等子物件。
此限制僅適用於明確的命名空間。未使用命名空間定義的類別和模組可以使用這些慣用語定義。
7.8.8 一個檔案,一個常數(在相同的頂層)
在 classic
模式下,您可以在相同的頂層定義多個常數,並將它們全部重新載入。例如,假設
# app/models/foo.rb
class Foo
end
class Bar
end
雖然無法自動載入 Bar
,但自動載入 Foo
也會將 Bar
標記為已自動載入。在 zeitwerk
模式下則不然,您需要將 Bar
移動到自己的檔案 bar.rb
中。一個檔案,一個常數。
這僅適用於與上面範例中相同的頂層常數。內部類別和模組是可以的。例如,考慮
# app/models/foo.rb
class Foo
class InnerClass
end
end
如果應用程式重新載入 Foo
,它也會重新載入 Foo::InnerClass
。
7.8.9 Spring 和 test
環境
如果程式碼有變更,Spring 會重新載入應用程式程式碼。在 test
環境中,您需要啟用重新載入才能使其運作
# config/environments/test.rb
config.cache_classes = false
否則您會收到此錯誤
reloading is disabled because config.cache_classes is true
7.8.10 Bootsnap
Bootsnap 應至少為 1.4.2 版。
除此之外,如果執行 Ruby 2.5,Bootsnap 需要停用 iseq 快取,因為解譯器中有一個錯誤。請確保在該情況下至少依賴 Bootsnap 1.4.4。
7.8.11 config.add_autoload_paths_to_load_path
為了向後相容,新的設定點 config.add_autoload_paths_to_load_path
預設為 true
,但允許您選擇不將自動載入路徑加入 $LOAD_PATH
。
這在大多數應用程式中都是有意義的,因為您永遠不應該要求 app/models
中的檔案,例如,而且 Zeitwerk 內部只使用絕對檔案名稱。
透過選擇不使用,您可以最佳化 $LOAD_PATH
查閱(減少要檢查的目錄),並節省 Bootsnap 的工作和記憶體消耗,因為它不需要為這些目錄建立索引。
7.8.12 線程安全
在傳統模式中,常數自動載入不是線程安全的,儘管 Rails 已有鎖定機制,例如在啟用自動載入時使 Web 請求線程安全,這在開發環境中很常見。
常數自動載入在 zeitwerk
模式下是線程安全的。例如,您現在可以在由 runner
命令執行的多線程腳本中自動載入。
7.8.13 config.autoload_paths 中的萬用字元
請注意類似以下的設定
config.autoload_paths += Dir["#{config.root}/lib/**/"]
config.autoload_paths
的每個元素都應代表頂層命名空間 (Object
),因此它們不能巢狀(上述說明的 concerns
目錄除外)。
要修正此問題,只需移除萬用字元
config.autoload_paths << "#{config.root}/lib"
7.8.14 預先載入和自動載入一致
在 classic
模式下,如果 app/models/foo.rb
定義了 Bar
,您將無法自動載入該檔案,但預先載入將會有效,因為它會盲目地遞迴載入檔案。如果您先測試預先載入,可能會因為稍後自動載入而導致執行失敗,這可能會成為錯誤的根源。
在 zeitwerk
模式下,這兩種載入模式是一致的,它們在相同的檔案中會失敗並產生錯誤。
7.8.15 如何在 Rails 6 中使用經典的自動載入器
應用程式可以載入 Rails 6 預設值,並且仍然可以使用經典的自動載入器,方法是透過以下方式設定 config.autoloader
# config/application.rb
config.load_defaults 6.0
config.autoloader = :classic
當在 Rails 6 應用程式中使用經典自動載入器時,建議將開發環境中的 Web 伺服器和背景處理器的並行層級設定為 1,因為存在線程安全問題。
7.9 Active Storage 指派行為變更
使用 Rails 5.2 的預設設定,指派給以 has_many_attached
宣告的附件集合會附加新檔案
class User < ApplicationRecord
has_many_attached :highlights
end
user.highlights.attach(filename: "funky.jpg")
user.highlights.count # => 1
blob = ActiveStorage::Blob.create_after_upload!(filename: "town.jpg")
user.update!(highlights: [ blob ])
user.highlights.count # => 2
user.highlights.first.filename # => "funky.jpg"
user.highlights.second.filename # => "town.jpg"
使用 Rails 6.0 的預設設定,指派給附件集合會取代現有檔案,而不是附加到它們。這與指派給集合關聯時的 Active Record 行為相符
user.highlights.attach(filename: "funky.jpg")
user.highlights.count # => 1
blob = ActiveStorage::Blob.create_after_upload!(filename: "town.jpg")
user.update!(highlights: [ blob ])
user.highlights.count # => 1
user.highlights.first.filename # => "town.jpg"
#attach
可用於新增附件,而無需移除現有的附件
blob = ActiveStorage::Blob.create_after_upload!(filename: "town.jpg")
user.highlights.attach(blob)
user.highlights.count # => 2
user.highlights.first.filename # => "funky.jpg"
user.highlights.second.filename # => "town.jpg"
現有的應用程式可以透過將 config.active_storage.replace_on_assign_to_many
設定為 true
來選擇加入此新行為。舊行為將在 Rails 7.0 中被棄用,並在 Rails 7.1 中移除。
7.10 自訂例外處理應用程式
無效的 Accept
或 Content-Type
請求標頭現在會引發例外狀況。預設的 config.exceptions_app
會特別處理該錯誤並進行補償。自訂例外應用程式也需要處理該錯誤,否則此類請求會導致 Rails 使用回退例外應用程式,並傳回 500 Internal Server Error
。
8 從 Rails 5.1 升級到 Rails 5.2
如需更多關於 Rails 5.2 所做的變更的資訊,請參閱版本說明。
8.1 Bootsnap
Rails 5.2 在新產生的應用程式 Gemfile中加入了 bootsnap gem。app:update
命令會在 boot.rb
中設定它。如果您想使用它,請將其加入 Gemfile
# Reduces boot times through caching; required in config/boot.rb
gem "bootsnap", require: false
否則請變更 boot.rb
以不使用 bootsnap。
8.2 簽名或加密 Cookie 中的到期時間現在會嵌入 Cookie 值中
為了提高安全性,Rails 現在也會將到期資訊嵌入加密或簽名的 Cookie 值中。
這個新嵌入的資訊會使這些 Cookie 與舊於 5.2 的 Rails 版本不相容。
如果您需要 5.1 及更舊版本讀取您的 Cookie,或者您仍在驗證您的 5.2 部署,並且希望允許您回滾,請將 Rails.application.config.action_dispatch.use_authenticated_cookie_encryption
設定為 false
。
9 從 Rails 5.0 升級到 Rails 5.1
如需更多關於 Rails 5.1 所做的變更的資訊,請參閱版本說明。
9.1 頂層 HashWithIndifferentAccess
已軟性棄用
如果您的應用程式使用頂層 HashWithIndifferentAccess
類別,您應該慢慢將程式碼移至改用 ActiveSupport::HashWithIndifferentAccess
。
這只是軟性棄用,這表示您的程式碼目前不會中斷,也不會顯示棄用警告,但此常數將在未來移除。
此外,如果您有相當舊的 YAML 文件,其中包含此類物件的傾印,您可能需要重新載入和傾印它們,以確保它們參照正確的常數,並且將來載入它們不會中斷。
9.2 application.secrets
現在會以符號形式載入所有鍵
如果您的應用程式在 config/secrets.yml
中儲存巢狀設定,則現在所有鍵都會以符號形式載入,因此應該變更使用字串的存取方式。
從
Rails.application.secrets[:smtp_settings]["address"]
到
Rails.application.secrets[:smtp_settings][:address]
9.3 移除了 render
中已棄用的 :text
和 :nothing
支援
如果您的控制器使用 render :text
,它們將不再有效。使用 text/plain
MIME 類型呈現文字的新方法是使用 render :plain
。
同樣地,render :nothing
也被移除,您應該使用 head
方法來傳送僅包含標頭的回應。例如,head :ok
會傳送 200 回應,且沒有要呈現的主體。
9.4 移除了已棄用的 redirect_to :back
支援
在 Rails 5.0 中,redirect_to :back
已被棄用。在 Rails 5.1 中,它已被完全移除。
作為替代方案,請使用 redirect_back
。務必注意 redirect_back
也會接受一個 fallback_location
選項,如果遺失 HTTP_REFERER
,將會使用該選項。
redirect_back(fallback_location: root_path)
10 從 Rails 4.2 升級到 Rails 5.0
如需更多關於 Rails 5.0 所做的變更的資訊,請參閱版本說明。
10.1 需要 Ruby 2.2.2+ 以上版本
從 Ruby on Rails 5.0 開始,僅支援 Ruby 2.2.2+ 以上版本。在繼續之前,請確保您使用的是 Ruby 2.2.2 或更新版本。
10.2 Active Record 模型現在預設繼承自 ApplicationRecord
在 Rails 4.2 中,Active Record 模型會繼承自 ActiveRecord::Base
。在 Rails 5.0 中,所有模型都會繼承自 ApplicationRecord
。
ApplicationRecord
是所有應用程式模型的新超類別,類似於應用程式控制器將 ApplicationController
子類別化,而不是 ActionController::Base
。這為應用程式提供了單一位置來設定應用程式範圍的模型行為。
當從 Rails 4.2 升級到 Rails 5.0 時,您需要在 app/models/
中建立一個 application_record.rb
檔案,並加入以下內容
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end
然後確保您的所有模型都繼承自它。
10.3 透過 throw(:abort)
停止回呼鏈
在 Rails 4.2 中,當 'before' 回呼在 Active Record 和 Active Model 中傳回 false
時,整個回呼鏈會停止。換句話說,不會執行後續的 'before' 回呼,也不會執行包裝在回呼中的動作。
在 Rails 5.0 中,於 Active Record 或 Active Model 回呼中回傳 false
將不會產生中止回呼鏈的副作用。相反地,必須透過呼叫 throw(:abort)
來明確中止回呼鏈。
當您從 Rails 4.2 升級至 Rails 5.0 時,在這些回呼中回傳 false
仍會中止回呼鏈,但您會收到關於此即將變更的棄用警告。
當您準備好時,您可以選擇啟用新行為並移除棄用警告,方法是將以下設定加入您的 config/application.rb
ActiveSupport.halt_callback_chains_on_return_false = false
請注意,此選項不會影響 Active Support 回呼,因為當任何值回傳時,它們永遠不會中止鏈。
請參閱 #17227 以了解更多詳細資訊。
10.4 ActiveJob 現在預設繼承自 ApplicationJob
在 Rails 4.2 中,Active Job 繼承自 ActiveJob::Base
。在 Rails 5.0 中,此行為已變更為現在繼承自 ApplicationJob
。
當從 Rails 4.2 升級至 Rails 5.0 時,您需要在 app/jobs/
中建立一個 application_job.rb
檔案,並加入以下內容
class ApplicationJob < ActiveJob::Base
end
然後確保您所有的 Job 類別都繼承自它。
請參閱 #19034 以了解更多詳細資訊。
10.5 Rails 控制器測試
10.5.1 將一些輔助方法提取到 rails-controller-testing
assigns
和 assert_template
已被提取到 rails-controller-testing
gem 中。若要在您的控制器測試中繼續使用這些方法,請將 gem "rails-controller-testing"
加入您的 Gemfile
。
如果您使用 RSpec 進行測試,請參閱 gem 的說明文件中所需的額外設定。
10.5.2 上傳檔案時的新行為
如果您在測試中使用 ActionDispatch::Http::UploadedFile
來上傳檔案,您需要改為使用類似的 Rack::Test::UploadedFile
類別。
請參閱 #26404 以了解更多詳細資訊。
10.6 生產環境啟動後停用自動載入
預設情況下,在生產環境中啟動後,自動載入現在會停用。
應用程式的預先載入是啟動過程的一部分,因此頂層常數是沒問題的,並且仍然會自動載入,不需要要求它們的檔案。
在較深層次,僅在執行時執行的常數(例如一般方法主體)也是沒問題的,因為定義它們的檔案會在啟動時被預先載入。
對於絕大多數應用程式,此變更不需要任何動作。但在極少數情況下,您的應用程式在生產環境中執行時需要自動載入,請將 Rails.application.config.enable_dependency_loading
設定為 true。
10.7 XML 序列化
ActiveModel::Serializers::Xml
已從 Rails 提取到 activemodel-serializers-xml
gem 中。若要在您的應用程式中繼續使用 XML 序列化,請將 gem "activemodel-serializers-xml"
加入您的 Gemfile
。
10.8 移除對舊版 mysql
資料庫介面的支援
Rails 5 移除對舊版 mysql
資料庫介面的支援。大多數使用者應該可以使用 mysql2
取代。當我們找到維護人員時,它將會轉換為單獨的 gem。
10.9 移除對 Debugger 的支援
Rails 5 要求的 Ruby 2.2 不支援 debugger
。請改用 byebug
。
10.10 使用 bin/rails
執行任務和測試
Rails 5 增加了透過 bin/rails
而不是 rake 執行任務和測試的功能。一般來說,這些變更是與 rake 並行進行的,但有些已完全移植過來。
若要使用新的測試執行器,只需輸入 bin/rails test
。
rake dev:cache
現在是 bin/rails dev:cache
。
在您應用程式的根目錄內執行 bin/rails
,以查看可用的命令清單。
10.11 ActionController::Parameters
不再繼承自 HashWithIndifferentAccess
在您的應用程式中呼叫 params
現在會回傳一個物件,而不是雜湊。如果您的參數已經被允許,則您不需要進行任何變更。如果您使用 map
和其他依賴於能夠讀取雜湊的方法,而不論 permitted?
為何,您都需要升級您的應用程式以先允許,然後再轉換為雜湊。
params.permit([:proceed_to, :return_to]).to_h
10.12 protect_from_forgery
現在預設為 prepend: false
protect_from_forgery
預設為 prepend: false
,這表示它將被插入到您在應用程式中呼叫它的回呼鏈中的那個點。如果您希望 protect_from_forgery
始終先執行,則您應該將您的應用程式變更為使用 protect_from_forgery prepend: true
。
10.13 預設範本處理器現在是 RAW
副檔名中沒有範本處理器的檔案將使用 raw 處理器呈現。先前 Rails 會使用 ERB 範本處理器呈現檔案。
如果您不希望透過 raw 處理器處理您的檔案,您應該將一個可以被適當範本處理器剖析的副檔名加入您的檔案。
10.14 為範本相依性新增萬用字元比對
您現在可以為您的範本相依性使用萬用字元比對。例如,如果您將您的範本定義為如下所示
<% # Template Dependency: recordings/threads/events/subscribers_changed %>
<% # Template Dependency: recordings/threads/events/completed %>
<% # Template Dependency: recordings/threads/events/uncompleted %>
您現在只需使用萬用字元呼叫一次相依性。
<% # Template Dependency: recordings/threads/events/* %>
10.15 ActionView::Helpers::RecordTagHelper
移至外部 gem (record_tag_helper)
content_tag_for
和 div_for
已被移除,改為僅使用 content_tag
。若要繼續使用較舊的方法,請將 record_tag_helper
gem 加入您的 Gemfile
gem "record_tag_helper", "~> 1.0"
請參閱 #18411 以了解更多詳細資訊。
10.16 移除對 protected_attributes
Gem 的支援
Rails 5 不再支援 protected_attributes
gem。
10.17 移除對 activerecord-deprecated_finders
gem 的支援
Rails 5 不再支援 activerecord-deprecated_finders
gem。
10.18 ActiveSupport::TestCase
預設測試順序現在是隨機的
當在您的應用程式中執行測試時,預設順序現在是 :random
而不是 :sorted
。使用以下設定選項將其設定回 :sorted
。
# config/environments/test.rb
Rails.application.configure do
config.active_support.test_order = :sorted
end
10.19 ActionController::Live
變成一個 Concern
如果您在包含在您的控制器中的另一個模組中包含 ActionController::Live
,那麼您也應該使用 ActiveSupport::Concern
擴展該模組。或者,您可以使用 self.included
hook 在 StreamingSupport
被包含後直接將 ActionController::Live
包含到控制器中。
這表示如果您的應用程式過去有自己的串流模組,則以下程式碼將在生產環境中中斷
# This is a work-around for streamed controllers performing authentication with Warden/Devise.
# See https://github.com/plataformatec/devise/issues/2332
# Authenticating in the router is another solution as suggested in that issue
class StreamingSupport
include ActionController::Live # this won't work in production for Rails 5
# extend ActiveSupport::Concern # unless you uncomment this line.
def process(name)
super(name)
rescue ArgumentError => e
if e.message == "uncaught throw :warden"
throw :warden
else
raise e
end
end
end
10.20 新的框架預設值
10.20.1 Active Record belongs_to
預設為必要選項
如果關聯不存在,belongs_to
現在預設會觸發驗證錯誤。
可以使用 optional: true
針對每個關聯關閉此功能。
此預設值將在新應用程式中自動設定。如果現有的應用程式想要加入此功能,則需要在初始化程式中開啟它
config.active_record.belongs_to_required_by_default = true
預設情況下,設定適用於您所有模型的全域設定,但您可以針對每個模型覆蓋它。這應該有助於您將所有模型遷移為預設需要它們的關聯。
class Book < ApplicationRecord
# model is not yet ready to have its association required by default
self.belongs_to_required_by_default = false
belongs_to(:author)
end
class Car < ApplicationRecord
# model is ready to have its association required by default
self.belongs_to_required_by_default = true
belongs_to(:pilot)
end
10.20.2 每個表單的 CSRF 權杖
Rails 5 現在支援每個表單的 CSRF 權杖,以減輕使用 JavaScript 建立的表單的程式碼注入攻擊。啟用此選項後,您應用程式中的表單將各自擁有自己的 CSRF 權杖,該權杖特定於該表單的操作和方法。
config.action_controller.per_form_csrf_tokens = true
10.20.3 使用來源檢查的偽造保護
您現在可以將您的應用程式設定為檢查 HTTP Origin
標頭是否應該針對網站的來源進行檢查,作為額外的 CSRF 防禦。在您的設定中將以下內容設定為 true
config.action_controller.forgery_protection_origin_check = true
10.20.4 允許設定 Action Mailer 佇列名稱
預設的郵件程式佇列名稱是 mailers
。此設定選項允許您全域變更佇列名稱。在您的設定中設定以下內容
config.action_mailer.deliver_later_queue_name = :new_queue_name
10.20.5 支援 Action Mailer 檢視中的片段快取
在您的設定中設定 config.action_mailer.perform_caching
以決定您的 Action Mailer 檢視是否應該支援快取。
config.action_mailer.perform_caching = true
10.20.6 設定 db:structure:dump
的輸出
如果您使用 schema_search_path
或其他 PostgreSQL 擴充功能,您可以控制如何傾印架構。設定為 :all
以產生所有傾印,或設定為 :schema_search_path
以從架構搜尋路徑產生。
config.active_record.dump_schemas = :all
10.20.7 設定 SSL 選項以啟用具有子網域的 HSTS
在您的設定中設定以下內容,以在使用子網域時啟用 HSTS
config.ssl_options = { hsts: { subdomains: true } }
10.20.8 保留接收者的時區
當使用 Ruby 2.4 時,您可以在呼叫 to_time
時保留接收者的時區。
ActiveSupport.to_time_preserves_timezone = false
10.21 JSON/JSONB 序列化的變更
在 Rails 5.0 中,JSON/JSONB 屬性的序列化和還原序列化方式已變更。現在,如果您將一個欄位設定為等於 String
,Active Record 將不再將該字串轉換為 Hash
,而是只會回傳字串。這不僅限於與模型互動的程式碼,也會影響 db/schema.rb
中的 :default
欄位設定。建議您不要將欄位設定為等於 String
,而是傳遞 Hash
,它會自動轉換為 JSON 字串並從中轉換。
11 從 Rails 4.1 升級到 Rails 4.2
11.1 Web Console
首先,在你的 Gemfile
中的 :development
群組加入 gem "web-console", "~> 2.0"
,並執行 bundle install
(當你升級 Rails 時,它不會被包含進來)。安裝完成後,你只需在任何你想啟用的視圖中加入對 console helper 的引用(例如:<%= console %>
)。此外,在開發環境中,任何你檢視的錯誤頁面也會提供一個 console。
11.2 Responders
respond_with
和類別層級的 respond_to
方法已被提取到 responders
gem 中。要使用它們,只需在你的 Gemfile
中加入 gem "responders", "~> 2.0"
。如果沒有在你的依賴項中包含 responders
gem,則對 respond_with
和 respond_to
的調用(再次強調,是在類別層級)將不再有效。
# 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
不受影響,不需要額外的 gem。
# 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
更多詳細資訊請參閱 #16526。
11.3 在 transaction 回呼中的錯誤處理
目前,Active Record 會抑制在 after_rollback
或 after_commit
回呼中引發的錯誤,並只將它們列印到日誌中。在下一個版本中,這些錯誤將不再被抑制。相反地,這些錯誤會像其他 Active Record 回呼一樣正常傳播。
當你定義一個 after_rollback
或 after_commit
回呼時,你將會收到一個關於這個即將到來的變更的棄用警告。當你準備好時,你可以選擇啟用新的行為,並透過在你的 config/application.rb
中加入以下配置來移除棄用警告:
config.active_record.raise_in_transactional_callbacks = true
11.4 測試案例的排序
在 Rails 5.0 中,測試案例預設會以隨機順序執行。為了預期此變更,Rails 4.2 引入了一個新的配置選項 active_support.test_order
,用於明確指定測試排序。這允許你透過將選項設定為 :sorted
來鎖定目前的行為,或是透過將選項設定為 :random
來選擇未來行為。
如果你沒有為此選項指定值,則會發出一個棄用警告。為了避免這種情況,請在你的測試環境中加入以下行:
# config/environments/test.rb
Rails.application.configure do
config.active_support.test_order = :sorted # or `:random` if you prefer
end
11.5 序列化屬性
當使用自訂編碼器(例如 serialize :metadata, JSON
)時,將 nil
指派給序列化的屬性會將其以 NULL
儲存到資料庫中,而不是透過編碼器傳遞 nil
值(例如,當使用 JSON
編碼器時為 "null"
)。
11.6 生產環境日誌級別
在 Rails 5 中,生產環境的預設日誌級別將會從 :info
變更為 :debug
。若要保留目前的預設值,請將以下行加入你的 production.rb
中:
# Set to `:info` to match the current default, or set to `:debug` to opt-into
# the future default.
config.log_level = :info
11.7 在 Rails 範本中的 after_bundle
如果你有一個 Rails 範本會將所有檔案加入版本控制,它會因為在 Bundler 之前執行而無法加入產生的 binstubs。
# template.rb
generate(:scaffold, "person name:string")
route "root to: 'people#index'"
rake("db:migrate")
git :init
git add: "."
git commit: %Q{ -m 'Initial commit' }
你現在可以將 git
調用包裝在 after_bundle
區塊中。它會在 binstubs 產生後執行。
# template.rb
generate(:scaffold, "person name:string")
route "root to: 'people#index'"
rake("db:migrate")
after_bundle do
git :init
git add: "."
git commit: %Q{ -m 'Initial commit' }
end
11.8 Rails HTML Sanitizer
在你的應用程式中,對於清理 HTML 片段有了一個新的選擇。原先的 html-scanner 方法現在正式被棄用,改為使用 Rails HTML Sanitizer
。
這表示 sanitize
、sanitize_css
、strip_tags
和 strip_links
方法由新的實作提供支援。
這個新的清理器內部使用 Loofah。Loofah 反過來使用 Nokogiri,它包裝了用 C 和 Java 編寫的 XML 解析器,因此無論你執行哪個 Ruby 版本,清理速度都應該更快。
新版本更新了 sanitize
,因此它可以使用 Loofah::Scrubber
進行強大的清理。 在此處查看一些 scrubbers 的範例。
還新增了兩個新的 scrubbers:PermitScrubber
和 TargetScrubber
。請閱讀 gem 的 readme 以取得更多資訊。
PermitScrubber
和 TargetScrubber
的文件說明了你如何完全控制元素何時以及如何被移除。
如果你的應用程式需要使用舊的清理器實作,請在你的 Gemfile
中包含 rails-deprecated_sanitizer
。
gem "rails-deprecated_sanitizer"
11.9 Rails DOM 測試
TagAssertions
模組(包含諸如 assert_tag
之類的方法)已被棄用,改為使用 SelectorAssertions
模組中的 assert_select
方法,該模組已被提取到 rails-dom-testing gem 中。
11.10 遮罩的身份驗證令牌
為了減輕 SSL 攻擊,form_authenticity_token
現在被遮罩,使其每次請求都不同。因此,令牌會透過解除遮罩然後解密來驗證。因此,任何用於驗證來自非 Rails 表單的請求的策略,如果依賴靜態 session CSRF 令牌,就必須考慮到這一點。
11.11 Action Mailer
先前,在 mailer 類別上呼叫 mailer 方法會直接執行對應的實例方法。隨著 Active Job 和 #deliver_later
的引入,情況不再如此。在 Rails 4.2 中,實例方法的調用會被延遲到呼叫 deliver_now
或 deliver_later
時。例如:
class Notifier < ActionMailer::Base
def notify(user)
puts "Called"
mail(to: user.email)
end
end
mail = Notifier.notify(user) # Notifier#notify is not yet called at this point
mail = mail.deliver_now # Prints "Called"
這對大多數應用程式來說應該不會造成任何明顯的差異。但是,如果你需要同步執行某些非 mailer 方法,並且你先前依賴同步代理行為,則應該將它們直接定義為 mailer 類別上的類別方法。
class Notifier < ActionMailer::Base
def self.broadcast_notifications(users, ...)
users.each { |user| Notifier.notify(user, ...) }
end
end
11.12 外鍵支援
遷移 DSL 已擴展為支援外鍵定義。如果你一直在使用 Foreigner gem,你可能需要考慮將其移除。請注意,Rails 的外鍵支援是 Foreigner 的子集。這表示並非每個 Foreigner 定義都可以完全由其 Rails 遷移 DSL 對應項取代。
遷移程序如下:
- 從
Gemfile
中移除gem "foreigner"
。 - 執行
bundle install
。 - 執行
bin/rake db:schema:dump
。 - 確保
db/schema.rb
包含每個外鍵定義及其必要的選項。
12 從 Rails 4.0 升級到 Rails 4.1
12.1 防止遠端 <script>
標籤的 CSRF 保護
或者,「哇!我的測試失敗了!!?」或「我的 <script>
小工具壞了!!」
跨網站請求偽造(CSRF)保護現在也涵蓋了具有 JavaScript 回應的 GET 請求。這可以防止第三方網站透過 <script>
標籤遠端引用你的 JavaScript 來提取敏感資料。
這表示你的功能和整合測試使用:
get :index, format: :js
現在將會觸發 CSRF 保護。切換到:
xhr :get, :index, format: :js
明確測試 XmlHttpRequest
。
你自己的 <script>
標籤也被視為跨來源,並且預設會被封鎖。如果你真的要從 <script>
標籤載入 JavaScript,你現在必須明確跳過這些動作的 CSRF 保護。
12.2 Spring
如果你想使用 Spring 作為你的應用程式預載器,你需要:
- 將
gem "spring", group: :development
加入你的Gemfile
。 - 使用
bundle install
安裝 spring。 - 使用
bundle exec spring binstub
產生 Spring binstub。
使用者定義的 rake tasks 預設會在 development
環境中執行。如果你希望它們在其他環境中執行,請查閱 Spring README。
12.3 config/secrets.yml
如果你想使用新的 secrets.yml
約定來儲存你的應用程式機密,你需要:
在你的
config
資料夾中建立一個secrets.yml
檔案,內容如下:development: secret_key_base: test: secret_key_base: production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
使用你現有在
secret_token.rb
初始化器中的secret_key_base
,為在生產環境中執行 Rails 應用程式的任何使用者設定SECRET_KEY_BASE
環境變數。或者,你可以直接將現有的secret_key_base
從secret_token.rb
初始化器複製到secrets.yml
中的production
區段,替換<%= ENV["SECRET_KEY_BASE"] %>
。移除
secret_token.rb
初始化器。使用
rake secret
為development
和test
區段產生新的金鑰。重新啟動你的伺服器。
12.4 測試 helper 的變更
如果你的測試 helper 包含對 ActiveRecord::Migration.check_pending!
的呼叫,則可以將其移除。當你 require "rails/test_help"
時,檢查現在會自動完成,儘管在你的 helper 中保留此行不會有任何損害。
12.5 Cookie 序列化程式
在 Rails 4.1 之前建立的應用程式使用 Marshal
將 cookie 值序列化到簽署和加密的 cookie jar 中。如果你想在你的應用程式中使用新的基於 JSON
的格式,你可以加入一個初始化檔案,內容如下:
Rails.application.config.action_dispatch.cookies_serializer = :hybrid
這會將你現有的 Marshal
序列化 cookie 透明地遷移到新的基於 JSON
的格式。
當使用 :json
或 :hybrid
序列化程式時,你應該注意並非所有的 Ruby 物件都可以序列化為 JSON。例如,Date
和 Time
物件將會被序列化為字串,而 Hash
的鍵將會被字串化。
class CookiesController < ApplicationController
def set_cookie
cookies.encrypted[:expiration_date] = Date.tomorrow # => Thu, 20 Mar 2014
redirect_to action: "read_cookie"
end
def read_cookie
cookies.encrypted[:expiration_date] # => "2014-03-20"
end
end
建議你只將簡單的資料(字串和數字)儲存在 cookies 中。如果你必須儲存複雜的物件,你將需要在後續請求中讀取值時手動處理轉換。
如果你使用 cookie session store,這也將適用於 session
和 flash
hash。
12.6 Flash 結構變更
Flash 訊息鍵會被標準化為字串。它們仍然可以使用符號或字串來存取。循環遍歷 flash 時將始終產生字串鍵。
flash["string"] = "a string"
flash[:symbol] = "a symbol"
# Rails < 4.1
flash.keys # => ["string", :symbol]
# Rails >= 4.1
flash.keys # => ["string", "symbol"]
請確保你將 Flash 訊息鍵與字串進行比較。
12.7 JSON 處理的變更
在 Rails 4.1 中,有幾個與 JSON 處理相關的主要變更。
12.7.1 移除 MultiJSON
MultiJSON 已達到其生命週期終點,並且已從 Rails 中移除。
如果你的應用程式目前直接依賴 MultiJSON,你有幾個選項:
將 'multi_json' 加入你的
Gemfile
。請注意,這在未來可能不再有效。改用
obj.to_json
和JSON.parse(str)
,避免使用 MultiJSON。
不要單純將 MultiJson.dump
和 MultiJson.load
替換成 JSON.dump
和 JSON.load
。這些 JSON gem API 用於序列化和反序列化任意 Ruby 物件,通常是不安全的。
12.7.2 JSON gem 相容性
過去,Rails 在與 JSON gem 的相容性方面存在一些問題。在 Rails 應用程式中使用 JSON.generate
和 JSON.dump
可能會產生意外的錯誤。
Rails 4.1 通過將其自身的編碼器與 JSON gem 隔離來修復了這些問題。JSON gem API 將像平常一樣運行,但它們將無法存取任何 Rails 特有的功能。例如
class FooBar
def as_json(options = nil)
{ foo: "bar" }
end
end
irb> FooBar.new.to_json
=> "{\"foo\":\"bar\"}"
irb> JSON.generate(FooBar.new, quirks_mode: true)
=> "\"#<FooBar:0x007fa80a481610>\""
12.7.3 新的 JSON 編碼器
Rails 4.1 中的 JSON 編碼器已重寫為利用 JSON gem。對於大多數應用程式來說,這應該是一個透明的更改。但是,作為重寫的一部分,以下功能已從編碼器中移除
- 循環資料結構偵測
- 對
encode_json
掛鉤的支援 - 將
BigDecimal
物件編碼為數字而不是字串的選項
如果您的應用程式依賴這些功能之一,您可以通過將 activesupport-json_encoder
gem 添加到您的 Gemfile
來恢復它們。
12.7.4 Time 物件的 JSON 表示
具有時間組件(Time
、DateTime
、ActiveSupport::TimeWithZone
)的物件的 #as_json
現在預設返回毫秒精度。如果您需要保留沒有毫秒精度的舊行為,請在初始化程式中設定以下內容
ActiveSupport::JSON::Encoding.time_precision = 0
12.8 在內聯回呼區塊中使用 return
先前,Rails 允許內聯回呼區塊以這種方式使用 return
class ReadOnlyModel < ActiveRecord::Base
before_save { return false } # BAD
end
此行為從未被有意支援。由於 ActiveSupport::Callbacks
內部機制的更改,Rails 4.1 中不再允許這樣做。在內聯回呼區塊中使用 return
語句會導致在執行回呼時引發 LocalJumpError
。
可以使用評估為返回值的重構方式來處理使用 return
的內聯回呼區塊
class ReadOnlyModel < ActiveRecord::Base
before_save { false } # GOOD
end
或者,如果偏好使用 return
,建議明確定義一個方法
class ReadOnlyModel < ActiveRecord::Base
before_save :before_save_callback # GOOD
private
def before_save_callback
false
end
end
此變更適用於 Rails 中大多數使用回呼的地方,包括 Active Record 和 Active Model 回呼,以及 Action Controller 中的篩選器(例如 before_action
)。
有關更多詳細資訊,請參閱此拉取請求。
12.9 在 Active Record fixtures 中定義的方法
Rails 4.1 在單獨的上下文中評估每個 fixture 的 ERB,因此在一個 fixture 中定義的 helper 方法在其他 fixture 中將不可用。
在多個 fixture 中使用的 helper 方法應在 test_helper.rb
中新引入的 ActiveRecord::FixtureSet.context_class
中包含的模組上定義。
module FixtureFileHelpers
def file_sha(path)
OpenSSL::Digest::SHA256.hexdigest(File.read(Rails.root.join("test/fixtures", path)))
end
end
ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers
12.10 I18n 強制執行可用的 locale
Rails 4.1 現在預設將 I18n 選項 enforce_available_locales
設定為 true
。這表示它將確保所有傳遞給它的 locale 都必須在 available_locales
清單中宣告。
若要停用它(並允許 I18n 接受任何 locale 選項),請將以下設定添加到您的應用程式
config.i18n.enforce_available_locales = false
請注意,此選項是作為安全措施添加的,以確保使用者輸入不能用作 locale 資訊,除非它先前已知。因此,建議不要停用此選項,除非您有充分的理由這樣做。
12.11 在 Relation 上呼叫 Mutator 方法
Relation
不再具有像 #map!
和 #delete_if
這樣的 mutator 方法。在使用這些方法之前,請通過呼叫 #to_a
將其轉換為 Array
。
它旨在防止在直接在 Relation
上呼叫 mutator 方法的程式碼中出現奇怪的錯誤和混淆。
# Instead of this
Author.where(name: "Hank Moody").compact!
# Now you have to do this
authors = Author.where(name: "Hank Moody").to_a
authors.compact!
12.12 預設範圍的變更
預設範圍不再被鏈式條件覆蓋。
在之前的版本中,當您在模型中定義 default_scope
時,它會被同一欄位中的鏈式條件覆蓋。現在它像任何其他範圍一樣合併。
之前
class User < ActiveRecord::Base
default_scope { where state: "pending" }
scope :active, -> { where state: "active" }
scope :inactive, -> { where state: "inactive" }
end
User.all
# SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
User.active
# SELECT "users".* FROM "users" WHERE "users"."state" = 'active'
User.where(state: "inactive")
# SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive'
之後
class User < ActiveRecord::Base
default_scope { where state: "pending" }
scope :active, -> { where state: "active" }
scope :inactive, -> { where state: "inactive" }
end
User.all
# SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
User.active
# SELECT "users".* FROM "users" WHERE "users"."state" = 'pending' AND "users"."state" = 'active'
User.where(state: "inactive")
# SELECT "users".* FROM "users" WHERE "users"."state" = 'pending' AND "users"."state" = 'inactive'
若要取得之前的行為,需要使用 unscoped
、unscope
、rewhere
或 except
明確移除 default_scope
條件。
class User < ActiveRecord::Base
default_scope { where state: "pending" }
scope :active, -> { unscope(where: :state).where(state: "active") }
scope :inactive, -> { rewhere state: "inactive" }
end
User.all
# SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
User.active
# SELECT "users".* FROM "users" WHERE "users"."state" = 'active'
User.inactive
# SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive'
12.13 從字串呈現內容
Rails 4.1 將 :plain
、:html
和 :body
選項引入 render
。這些選項現在是呈現基於字串的內容的首選方式,因為它允許您指定要以哪種內容類型傳送回應。
render :plain
會將內容類型設定為text/plain
render :html
會將內容類型設定為text/html
render :body
將不設定內容類型標頭。
從安全角度來看,如果您不希望回應本文中包含任何標記,則應該使用 render :plain
,因為大多數瀏覽器會為您轉義回應中的不安全內容。
我們將在未來版本中棄用 render :text
的使用。因此,請開始使用更精確的 :plain
、:html
和 :body
選項。使用 render :text
可能會造成安全風險,因為內容是以 text/html
傳送的。
12.14 PostgreSQL JSON 和 hstore 資料類型
Rails 4.1 會將 json
和 hstore
欄位對應到以字串為鍵的 Ruby Hash
。在較早的版本中,使用 HashWithIndifferentAccess
。這表示不再支援符號存取。基於 json
或 hstore
欄位的 store_accessors
也是如此。請務必一致地使用字串鍵。
12.15 明確區塊使用於 ActiveSupport::Callbacks
Rails 4.1 現在要求在呼叫 ActiveSupport::Callbacks.set_callback
時傳遞明確的區塊。此變更源於 ActiveSupport::Callbacks
為 4.1 版本進行了大幅重寫。
# Previously in Rails 4.0
set_callback :save, :around, ->(r, &block) { stuff; result = block.call; stuff }
# Now in Rails 4.1
set_callback :save, :around, ->(r, block) { stuff; result = block.call; stuff }
13 從 Rails 3.2 升級到 Rails 4.0
如果您的應用程式目前使用任何低於 3.2.x 的 Rails 版本,您應該先升級到 Rails 3.2,然後再嘗試升級到 Rails 4.0。
以下變更旨在將您的應用程式升級到 Rails 4.0。
13.1 HTTP PATCH
當在 config/routes.rb
中宣告 RESTful 資源時,Rails 4 現在使用 PATCH
作為更新的主要 HTTP 動詞。仍然使用 update
動作,並且 PUT
請求也將繼續路由到 update
動作。因此,如果您僅使用標準的 RESTful 路由,則無需進行任何更改
resources :users
<%= form_for @user do |f| %>
class UsersController < ApplicationController
def update
# No change needed; PATCH will be preferred, and PUT will still work.
end
end
但是,如果您使用 form_for
更新資源並結合使用 PUT
HTTP 方法的自訂路由,則需要進行更改
resources :users do
put :update_name, on: :member
end
<%= form_for [ :update_name, @user ] do |f| %>
class UsersController < ApplicationController
def update_name
# Change needed; form_for will try to use a non-existent PATCH route.
end
end
如果該動作未在公共 API 中使用,並且您可以自由更改 HTTP 方法,則可以更新路由以使用 patch
而不是 put
resources :users do
patch :update_name, on: :member
end
Rails 4 中對 /users/:id
的 PUT
請求會像今天一樣路由到 update
。因此,如果您的 API 取得真正的 PUT 請求,它將會正常運作。路由器也會將對 /users/:id
的 PATCH
請求路由到 update
動作。
如果該動作正在公共 API 中使用,並且您無法更改所使用的 HTTP 方法,則可以更新表單以使用 PUT
方法
<%= form_for [ :update_name, @user ], method: :put do |f| %>
有關 PATCH 以及為何進行此變更的更多資訊,請參閱 Rails 部落格上的這篇文章。
13.1.1 關於媒體類型的注意事項
PATCH
動詞的勘誤指定應將「diff」媒體類型與 PATCH
一起使用。其中一種格式是JSON Patch。雖然 Rails 本身不支援 JSON Patch,但很容易新增支援
# in your controller:
def update
respond_to do |format|
format.json do
# perform a partial update
@article.update params[:article]
end
format.json_patch do
# perform sophisticated change
end
end
end
# config/initializers/json_patch.rb
Mime::Type.register "application/json-patch+json", :json_patch
由於 JSON Patch 最近才被制定為 RFC,因此目前還沒有很多優秀的 Ruby 程式庫。Aaron Patterson 的 hana 就是這樣一個 gem,但它並不完全支援規格中的最後幾個變更。
13.2 Gemfile
Rails 4.0 從 Gemfile
中移除了 assets
群組。升級時您需要從 Gemfile
中移除該行。您還應該更新您的應用程式檔案 (在 config/application.rb
中)
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
13.3 vendor/plugins
Rails 4.0 不再支援從 vendor/plugins
載入外掛程式。您必須將外掛程式提取到 gem 並將其新增到 Gemfile
中來替換它們。如果您選擇不將它們變成 gem,您可以將它們移動到例如 lib/my_plugin/*
並在 config/initializers/my_plugin.rb
中新增適當的初始化程式。
13.4 Active Record
Rails 4.0 由於 與關聯的一些不一致,已從 Active Record 中移除了身分對應。如果您已在您的應用程式中手動啟用它,您將必須移除不再有效的以下設定:
config.active_record.identity_map
。集合關聯中的
delete
方法現在可以接收Integer
或String
引數作為記錄 ID,以及記錄,幾乎與destroy
方法一樣。先前,它會為此類引數引發ActiveRecord::AssociationTypeMismatch
。從 Rails 4.0 開始,delete
會在刪除記錄之前自動嘗試尋找與給定 ID 匹配的記錄。在 Rails 4.0 中,當欄位或表格被重新命名時,相關的索引也會被重新命名。如果您有重新命名索引的遷移,則不再需要它們。
Rails 4.0 已將
serialized_attributes
和attr_readonly
變更為僅限於類別方法。您不應該使用實例方法,因為它現在已棄用。您應該將它們變更為使用類別方法,例如self.serialized_attributes
變更為self.class.serialized_attributes
。當使用預設編碼器時,將
nil
指派給序列化的屬性會將其儲存到資料庫為NULL
,而不是通過 YAML 傳遞nil
值("--- \n...\n"
)。Rails 4.0 已刪除了
attr_accessible
和attr_protected
功能,轉而使用 Strong Parameters。您可以使用 Protected Attributes gem 實現平穩的升級路徑。如果您沒有使用 Protected Attributes,則可以移除任何與此 gem 相關的選項,例如
whitelist_attributes
或mass_assignment_sanitizer
選項。Rails 4.0 要求範圍使用可呼叫的物件,例如 Proc 或 lambda
scope :active, where(active: true) # becomes scope :active, -> { where active: true }
Rails 4.0 已棄用
ActiveRecord::Fixtures
,轉而使用ActiveRecord::FixtureSet
。Rails 4.0 已棄用
ActiveRecord::TestCase
,轉而使用ActiveSupport::TestCase
。Rails 4.0 已棄用基於雜湊的舊樣式 finder API。這表示先前接受「finder 選項」的方法不再這樣做。例如,
Book.find(:all, conditions: { name: '1984' })
已被棄用,轉而使用Book.where(name: '1984')
除了
find_by_...
和find_by_...!
之外,所有動態方法都已棄用。以下是您可以處理這些變更的方式find_all_by_...
變成where(...)
。find_last_by_...
變成where(...).last
。scoped_by_...
變成where(...)
。find_or_initialize_by_...
變成find_or_initialize_by(...)
。find_or_create_by_...
變成find_or_create_by(...)
。
請注意,
where(...)
會返回關聯,而不是像舊的 finder 一樣返回陣列。如果您需要Array
,請使用where(...).to_a
。這些等效的方法可能不會執行與先前實作相同的 SQL。
若要重新啟用舊的 finder,您可以使用 activerecord-deprecated_finders gem。
Rails 4.0 已將
has_and_belongs_to_many
關聯的預設聯結表格變更為剝離第二個表格名稱的常見前綴。任何具有常見前綴的模型之間的現有has_and_belongs_to_many
關聯都必須使用join_table
選項指定。例如class CatalogCategory < ActiveRecord::Base has_and_belongs_to_many :catalog_products, join_table: "catalog_categories_catalog_products" end class CatalogProduct < ActiveRecord::Base has_and_belongs_to_many :catalog_categories, join_table: "catalog_categories_catalog_products" end
請注意,前綴也會考慮範圍,因此
Catalog::Category
和Catalog::Product
或Catalog::Category
和CatalogProduct
之間的關聯也需要進行類似的更新。
13.5 Active Resource
Rails 4.0 將 Active Resource 提取成獨立的 gem。如果您仍然需要此功能,可以在您的 Gemfile
中加入 Active Resource gem。
13.6 Active Model
Rails 4.0 變更了錯誤如何與
ActiveModel::Validations::ConfirmationValidator
連結的方式。現在,當確認驗證失敗時,錯誤會附加到:#{attribute}_confirmation
而不是attribute
。Rails 4.0 將
ActiveModel::Serializers::JSON.include_root_in_json
的預設值變更為false
。現在,Active Model Serializers 和 Active Record 物件具有相同的預設行為。這表示您可以註解或移除config/initializers/wrap_parameters.rb
檔案中的下列選項# Disable root element in JSON by default. # ActiveSupport.on_load(:active_record) do # self.include_root_in_json = false # end
13.7 Action Pack
Rails 4.0 引入了
ActiveSupport::KeyGenerator
,並以此作為產生和驗證簽名 Cookie(以及其他事項)的基礎。如果您保留現有的secret_token
並加入新的secret_key_base
,則使用 Rails 3.x 產生的現有簽名 Cookie 將會被透明地升級。# config/initializers/secret_token.rb Myapp::Application.config.secret_token = "existing secret token" Myapp::Application.config.secret_key_base = "new secret key base"
請注意,您應該等到 100% 的使用者都使用 Rails 4.x,並且相當確定您不需要回滾到 Rails 3.x 時,再設定
secret_key_base
。這是因為基於 Rails 4.x 中新的secret_key_base
簽名的 Cookie 與 Rails 3.x 不向後相容。您可以自由地保留現有的secret_token
,不設定新的secret_key_base
,並忽略棄用警告,直到您相當確定升級已完成為止。如果您依賴外部應用程式或 JavaScript 能夠讀取 Rails 應用程式的簽名 Session Cookie(或一般簽名 Cookie)的能力,您應該在解除這些問題的耦合之前,不要設定
secret_key_base
。如果設定了
secret_key_base
,Rails 4.0 會加密基於 Cookie 的 Session 的內容。Rails 3.x 會簽名,但不會加密基於 Cookie 的 Session 的內容。簽名 Cookie 在驗證是由您的應用程式產生且防竄改方面是「安全的」。但是,終端使用者可以檢視內容,而加密內容可以消除這個顧慮,且不會造成顯著的效能損失。請閱讀 Pull Request #9978 以取得有關移至加密 Session Cookie 的詳細資訊。
Rails 4.0 移除了
ActionController::Base.asset_path
選項。請使用 assets pipeline 功能。Rails 4.0 已棄用
ActionController::Base.page_cache_extension
選項。請改用ActionController::Base.default_static_extension
。Rails 4.0 已從 Action Pack 中移除 Action 和 Page 快取。您需要加入
actionpack-action_caching
gem 才能在控制器中使用caches_action
,並加入actionpack-page_caching
才能使用caches_page
。Rails 4.0 移除了 XML 參數解析器。如果您需要此功能,您需要加入
actionpack-xml_parser
gem。Rails 4.0 變更了使用符號或傳回 nil 的 Proc 來設定預設
layout
查找的方式。若要取得「無 Layout」的行為,請傳回 false 而不是 nil。Rails 4.0 將預設的 memcached 用戶端從
memcache-client
變更為dalli
。若要升級,只需將gem "dalli"
加入您的Gemfile
。Rails 4.0 棄用控制器中的
dom_id
和dom_class
方法(在 View 中仍可正常使用)。您需要在需要此功能的控制器中包含ActionView::RecordIdentifier
模組。Rails 4.0 棄用
link_to
輔助方法的:confirm
選項。您應該改為依賴 data 屬性(例如data: { confirm: 'Are you sure?' }
)。此棄用也與基於此輔助方法的其他輔助方法相關(例如link_to_if
或link_to_unless
)。Rails 4.0 變更了
assert_generates
、assert_recognizes
和assert_routing
的運作方式。現在,所有這些斷言都會引發Assertion
而不是ActionController::RoutingError
。如果定義了衝突的具名路由,Rails 4.0 會引發
ArgumentError
。這可以透過明確定義的具名路由或resources
方法觸發。以下是兩個與名為example_path
的路由衝突的範例get "one" => "test#example", as: :example get "two" => "test#example", as: :example
resources :examples get "clashing/:id" => "test#example", as: :example
在第一種情況下,您可以簡單地避免對多個路由使用相同的名稱。在第二種情況下,您可以使用
resources
方法提供的only
或except
選項來限制建立的路由,如路由指南中所述。Rails 4.0 也變更了繪製 Unicode 字元路由的方式。現在您可以直接繪製 Unicode 字元路由。如果您已經繪製了這類路由,您必須變更它們,例如
get Rack::Utils.escape("こんにちは"), controller: "welcome", action: "index"
變成
get "こんにちは", controller: "welcome", action: "index"
使用
match
的 Rails 4.0 路由必須指定請求方法。例如# Rails 3.x match "/" => "root#index" # becomes match "/" => "root#index", via: :get # or get "/" => "root#index"
Rails 4.0 已移除
ActionDispatch::BestStandardsSupport
中介軟體,<!DOCTYPE html>
已經根據 https://msdn.microsoft.com/en-us/library/jj676915(v=vs.85).aspx 觸發標準模式,而 ChromeFrame 標頭已移至config.action_dispatch.default_headers
。請記住,您還必須從應用程式碼中移除對中介軟體的任何參考,例如
# Raise exception config.middleware.insert_before(Rack::Lock, ActionDispatch::BestStandardsSupport)
同時檢查您的環境設定是否有
config.action_dispatch.best_standards_support
,如果存在則將其移除。Rails 4.0 允許透過設定
config.action_dispatch.default_headers
來設定 HTTP 標頭。預設值如下config.action_dispatch.default_headers = { "X-Frame-Options" => "SAMEORIGIN", "X-XSS-Protection" => "1; mode=block" }
請注意,如果您的應用程式依賴在
<frame>
或<iframe>
中載入特定頁面,則您可能需要明確地將X-Frame-Options
設定為ALLOW-FROM ...
或ALLOWALL
。在 Rails 4.0 中,預編譯 Assets 不會再自動從
vendor/assets
和lib/assets
複製非 JS/CSS Assets。Rails 應用程式和引擎開發人員應該將這些 Assets 放入app/assets
或設定config.assets.precompile
。在 Rails 4.0 中,當 Action 無法處理請求格式時,會引發
ActionController::UnknownFormat
。預設情況下,此例外會以回應 406 Not Acceptable 來處理,但您現在可以覆寫此例外。在 Rails 3 中,始終會傳回 406 Not Acceptable。沒有任何覆寫。在 Rails 4.0 中,當
ParamsParser
無法解析請求參數時,會引發泛型ActionDispatch::ParamsParser::ParseError
例外。您會想要救援此例外,而不是低階的MultiJson::DecodeError
,例如。在 Rails 4.0 中,當引擎掛載在從 URL 前綴提供的應用程式上時,
SCRIPT_NAME
會正確地巢狀化。您不再需要設定default_url_options[:script_name]
來解決覆寫的 URL 前綴。Rails 4.0 已棄用
ActionController::Integration
,而改用ActionDispatch::Integration
。Rails 4.0 已棄用
ActionController::IntegrationTest
,而改用ActionDispatch::IntegrationTest
。Rails 4.0 已棄用
ActionController::PerformanceTest
,而改用ActionDispatch::PerformanceTest
。Rails 4.0 已棄用
ActionController::AbstractRequest
,而改用ActionDispatch::Request
。Rails 4.0 已棄用
ActionController::Request
,而改用ActionDispatch::Request
。Rails 4.0 已棄用
ActionController::AbstractResponse
,而改用ActionDispatch::Response
。Rails 4.0 已棄用
ActionController::Response
,而改用ActionDispatch::Response
。Rails 4.0 已棄用
ActionController::Routing
,而改用ActionDispatch::Routing
。
13.8 Active Support
Rails 4.0 移除了 ERB::Util#json_escape
的 j
別名,因為 j
已用於 ActionView::Helpers::JavaScriptHelper#escape_javascript
。
13.8.1 快取
Rails 3.x 和 4.0 之間的快取方法有所變更。您應該變更快取命名空間,並使用冷快取進行部署。
13.9 輔助方法載入順序
在 Rails 4.0 中,從多個目錄載入輔助方法的順序已變更。先前,它們會被收集起來,然後按字母順序排序。升級到 Rails 4.0 後,輔助方法會保留已載入目錄的順序,並且只會在每個目錄內按字母順序排序。除非您明確使用 helpers_path
參數,否則此變更只會影響從引擎載入輔助方法的方式。如果您依賴排序,您應該檢查升級後是否可使用正確的方法。如果您想要變更載入引擎的順序,您可以使用 config.railties_order=
方法。
13.10 Active Record Observer 和 Action Controller Sweeper
ActiveRecord::Observer
和 ActionController::Caching::Sweeper
已提取到 rails-observers
gem。如果您需要這些功能,您需要加入 rails-observers
gem。
13.11 sprockets-rails
assets:precompile:primary
和assets:precompile:all
已移除。請改用assets:precompile
。config.assets.compress
選項應該變更為config.assets.js_compressor
,例如config.assets.js_compressor = :uglifier
13.12 sass-rails
- 已棄用帶有兩個參數的
asset-url
。例如:asset-url("rails.png", image)
變成asset-url("rails.png")
。
14 從 Rails 3.1 升級到 Rails 3.2
如果您的應用程式目前使用任何低於 3.1.x 版本的 Rails,您應該先升級到 Rails 3.1,再嘗試更新到 Rails 3.2。
以下變更旨在將您的應用程式升級到最新 3.2.x 版本的 Rails。
14.1 Gemfile
請對您的 Gemfile
進行以下變更。
gem "rails", "3.2.21"
group :assets do
gem "sass-rails", "~> 3.2.6"
gem "coffee-rails", "~> 3.2.2"
gem "uglifier", ">= 1.0.3"
end
14.2 config/environments/development.rb
有幾個新的組態設定,您應該將其加入您的開發環境
# Raise exception on mass assignment protection for Active Record models
config.active_record.mass_assignment_sanitizer = :strict
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
config.active_record.auto_explain_threshold_in_seconds = 0.5
14.3 config/environments/test.rb
mass_assignment_sanitizer
組態設定也應該加入 config/environments/test.rb
# Raise exception on mass assignment protection for Active Record models
config.active_record.mass_assignment_sanitizer = :strict
14.4 vendor/plugins
Rails 3.2 棄用 vendor/plugins
,而 Rails 4.0 將完全移除它們。雖然這不是 Rails 3.2 升級的必要步驟,但您可以開始將任何外掛程式提取為 gem,並將其加入您的 Gemfile
來取代它們。如果您選擇不將它們設為 gem,您可以將它們移至例如 lib/my_plugin/*
,並在 config/initializers/my_plugin.rb
中加入適當的初始化設定。
14.5 Active Record
已從 belongs_to
中移除選項 :dependent => :restrict
。如果您想要防止在有任何關聯物件時刪除物件,您可以設定 :dependent => :destroy
,並在從任何關聯物件的銷毀回呼檢查關聯是否存在後傳回 false
。
15 從 Rails 3.0 升級到 Rails 3.1
如果您的應用程式目前使用任何低於 3.0.x 版本的 Rails,您應該先升級到 Rails 3.0,再嘗試更新到 Rails 3.1。
以下變更旨在將您的應用程式升級到 Rails 3.1.12(Rails 的最後一個 3.1.x 版本)。
15.1 Gemfile
請對您的 Gemfile
進行以下變更。
gem "rails", "3.1.12"
gem "mysql2"
# Needed for the new asset pipeline
group :assets do
gem "sass-rails", "~> 3.1.7"
gem "coffee-rails", "~> 3.1.1"
gem "uglifier", ">= 1.0.3"
end
# jQuery is the default JavaScript library in Rails 3.1
gem "jquery-rails"
15.2 config/application.rb
asset pipeline 需要以下新增內容
config.assets.enabled = true
config.assets.version = "1.0"
如果您的應用程式正在使用資源的 "/assets" 路由,您可能會想要變更用於 assets 的前綴,以避免衝突
# Defaults to '/assets'
config.assets.prefix = "/asset-files"
15.3 config/environments/development.rb
移除 RJS 設定 config.action_view.debug_rjs = true
。
如果您啟用 asset pipeline,請加入這些設定
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets
config.assets.debug = true
15.4 config/environments/production.rb
同樣地,以下大部分變更都是針對 asset pipeline。您可以在Asset Pipeline 指南中閱讀更多相關資訊。
# Compress JavaScripts and CSS
config.assets.compress = true
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = false
# Generate digests for assets URLs
config.assets.digest = true
# Defaults to Rails.root.join("public/assets")
# config.assets.manifest = YOUR_PATH
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
# config.assets.precompile += %w( admin.js admin.css )
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
15.5 config/environments/test.rb
您可以透過對測試環境的這些新增內容來協助測試效能
# Configure static asset server for tests with Cache-Control for performance
config.public_file_server.enabled = true
config.public_file_server.headers = {
"Cache-Control" => "public, max-age=3600"
}
15.6 config/initializers/wrap_parameters.rb
如果您想要將參數包裝到巢狀雜湊中,請新增此檔案並包含以下內容。這在新應用程式中預設為開啟。
# Be sure to restart your server when you modify this file.
# This file contains settings for ActionController::ParamsWrapper which
# is enabled by default.
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
ActiveSupport.on_load(:action_controller) do
wrap_parameters format: [:json]
end
# Disable root element in JSON by default.
ActiveSupport.on_load(:active_record) do
self.include_root_in_json = false
end
15.7 config/initializers/session_store.rb
您需要將您的 Session 金鑰變更為新的金鑰,或移除所有 Session
# in config/initializers/session_store.rb
AppName::Application.config.session_store :cookie_store, key: "SOMETHINGNEW"
或
$ bin/rake db:sessions:clear
15.8 移除 View 中 asset 輔助方法參考中的 :cache 和 :concat 選項
- 使用 Asset Pipeline 時,不再使用 :cache 和 :concat 選項,請從您的 View 中刪除這些選項。