edge
更多資訊請參考 rubyonrails.org: 更多 Ruby on Rails

Ruby on Rails 4.2 發行說明

Rails 4.2 的亮點:

這些發行說明僅涵蓋主要更改。要了解其他功能、錯誤修復和更改,請參閱變更日誌或檢查 GitHub 上主要 Rails 存儲庫的 提交列表

1 升級到 Rails 4.2

如果您正在升級現有應用程式,建議在進行升級之前先進行良好的測試覆蓋。如果尚未升級到 Rails 4.1,請先升級到該版本,然後確保應用程式運行正常,然後再嘗試升級到 Rails 4.2。在升級時要注意的事項列表可在指南 升級 Ruby on Rails 中找到。

2 主要功能

2.1 Active Job

Active Job 是 Rails 4.2 中的新框架。它是在排程系統(如 ResqueDelayed JobSidekiq 等)之上的通用介面。

使用 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 中的一組性能改進,可以使常見的 findfind_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中。目前,只有mysqlmysql2postgresql適配器支援外鍵。

# 添加一個外鍵到`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_keyremove_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淨化器已經被一個基於LoofahNokogiri的新的、更強大、更靈活的實現所取代。新的淨化器更安全,其淨化功能更強大和靈活。

由於新的算法,對於某些極端輸入,淨化後的輸出可能會有所不同。

如果您對舊淨化器的精確輸出有特殊需求,可以將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&amp;T),現在是評估的(例如AT&T)。

    # 內容: <p>AT&amp;T</p>
    
    # 之前:
    assert_select('p', 'AT&amp;T')  # => true
    assert_select('p', 'AT&T')      # => false
    
    # 現在:
    assert_select('p', 'AT&T')      # => true
    assert_select('p', 'AT&amp;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_tagassert_no_tagfind_tagfind_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 中刪除。

    (提交 12

  • render nothing: true 或渲染 nil 內容不再在響應內容中添加單個空格填充。 (拉取請求

  • Rails 現在自動在 ETags 中包含模板的摘要。 (拉取請求

  • 傳遞給 URL 助手函數的片段現在會自動進行轉義。 (提交)

  • 引入了always_permitted_parameters選項,用於配置全局允許的參數。該配置的默認值為['controller', 'action']。 (拉取請求)

  • RFC 4791中添加了HTTP方法MKCALENDAR。 (拉取請求)

  • *_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特殊局部變量,用於與使用集合呈現的局部模板一起使用。它通過indexsizefirst?last?方法提供對迭代的當前狀態的訪問。 (拉取請求)

  • Placeholder I18n遵循與label I18n相同的慣例。 (拉取請求)

7 Action Mailer

詳細更改請參閱[更新日誌][action-mailer]。

7.1 廢棄

  • 在郵件中廢棄了*_path輔助方法。請始終使用*_url輔助方法。 (拉取請求)

  • 廢棄了deliver / deliver!,改用deliver_now / deliver_now!。 (拉取請求)

7.2 重要更改

  • 在模板中,link_tourl_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::Migrationproper_table_name實例方法。 (拉取請求)

  • 刪除了未使用的:timestamp類型。在所有情況下,將其透明地別名為:datetime。 修正了在將列類型傳送到Active Record之外(例如XML序列化)時的不一致性。 (拉取請求)

8.2 廢棄項目

  • 廢棄了在after_commitafter_rollback中吞噬錯誤的功能。 (拉取請求)

  • 廢棄了對has_many :through關聯自動檢測計數緩存的支援。現在應該手動在 通過記錄的has_manybelongs_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_timestampst.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 重要更改

  • SchemaDumpercreate_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)

  • 為 MySQL 5.6 及以上版本添加了對於小數秒的支持。 (Pull Request 1, 2)

  • 添加了 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#agoNumeric#untilNumeric#sinceNumeric#from_now 方法。 (Commit)

  • 刪除了 ActiveSupport::Callbacks 的基於字符串的終止符的已棄用方法。 (Pull Request)

10.2 棄用

  • 棄用 Kernel#silence_stderrKernel#captureKernel#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。 (提交)

  • Object#tryObject#try! 現在可以在區塊中不使用顯式接收器來使用。 (提交, 拉取請求)

  • travel_to 測試輔助方法現在將 usec 組件截斷為 0。 (提交)

  • 引入了 Object#itself 作為一個身份函數。 (提交 1, 2)

  • Object#with_options 現在可以在區塊中不使用顯式接收器來使用。 (拉取請求)

  • 引入了 String#truncate_words 來按單詞數截斷字符串。 (拉取請求)

  • 添加了 Hash#transform_valuesHash#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 論壇 上進行。