更多資訊請至 rubyonrails.org:

Ruby on Rails 3.2 發行說明

Rails 3.2 的重點

  • 更快的開發模式
  • 新的路由引擎
  • 自動查詢說明
  • 標籤記錄

這些發行說明僅涵蓋主要變更。若要瞭解各種錯誤修正和變更,請參閱變更日誌或查看 GitHub 上主 Rails 儲存庫中的 提交清單

1 升級至 Rails 3.2

如果您要升級現有的應用程式,最好在開始之前有良好的測試涵蓋率。您也應該先升級至 Rails 3.1(如果您尚未升級),並確保您的應用程式在嘗試更新至 Rails 3.2 之前仍然能如預期運作。然後注意下列變更

1.1 Rails 3.2 至少需要 Ruby 1.8.7

Rails 3.2 需要 Ruby 1.8.7 或更高版本。已正式放棄對所有先前 Ruby 版本的支援,您應該盡早升級。Rails 3.2 也與 Ruby 1.9.2 相容。

請注意,Ruby 1.8.7 p248 和 p249 有導致 Rails 當機的序列化錯誤。Ruby Enterprise Edition 自 1.8.7-2010.02 發行以來已修正這些錯誤。在 1.9 方面,Ruby 1.9.1 無法使用,因為它會直接發生區段錯誤,因此如果您想使用 1.9.x,請跳至 1.9.2 或 1.9.3 以順利執行。

1.2 應用程式中要更新的內容

  • 更新您的 Gemfile 以依賴

    • rails = 3.2.0
    • sass-rails ~> 3.2.3
    • coffee-rails ~> 3.2.1
    • uglifier >= 1.0.3
  • Rails 3.2 棄用了 vendor/plugins,而 Rails 4.0 將完全移除它們。您可以開始將這些外掛程式取代為將它們提取為 gem,並將它們新增至您的 Gemfile 中。如果您選擇不將它們設為 gem,您可以將它們移至,例如,lib/my_plugin/*,並在 config/initializers/my_plugin.rb 中新增適當的初始化設定。

  • 有一些新的組態變更,您會想要在 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
    

    mass_assignment_sanitizer 組態也需要在 config/environments/test.rb 中新增

    # Raise exception on mass assignment protection for Active Record models
    config.active_record.mass_assignment_sanitizer = :strict
    

1.3 引擎中要更新的內容

script/rails 中註解下方的程式碼取代為以下內容

ENGINE_ROOT = File.expand_path('../..', __FILE__)
ENGINE_PATH = File.expand_path('../../lib/your_engine_name/engine', __FILE__)

require "rails/all"
require "rails/engine/commands"

2 建立 Rails 3.2 應用程式

# You should have the 'rails' RubyGem installed
$ rails new myapp
$ cd myapp

2.1 供應商 Gem

Rails 現在使用應用程式根目錄中的 Gemfile 來判斷應用程式啟動所需的 gem。這個 GemfileBundler gem 處理,然後安裝所有相依性。它甚至可以將所有相依性在本機安裝到您的應用程式中,使其不依賴系統 gem。

更多資訊:Bundler 首頁

2.2 使用 Edge 版本

BundlerGemfile 讓使用新的專用 bundle 命令來凍結您的 Rails 應用程式變得輕而易舉。如果您想直接從 Git 儲存庫捆綁,您可以傳遞 --edge 旗標

$ rails new myapp --edge

如果您有 Rails 儲存庫的本機簽出,並想使用它產生應用程式,您可以傳遞 --dev 旗標

$ ruby /path/to/rails/railties/bin/rails new myapp --dev

3 主要功能

3.1 更快的開發模式與路由

Rails 3.2 隨附一個明顯更快的開發模式。受 Active Reload 的啟發,Rails 僅在檔案實際變更時重新載入類別。在較大的應用程式上,效能提升是顯著的。由於新的 Journey 引擎,路由辨識也變得更快。

3.2 自動查詢說明

Rails 3.2 隨附一個不錯的功能,透過在 ActiveRecord::Relation 中定義 explain 方法來說明 Arel 產生的查詢。例如,您可以執行類似 puts Person.active.limit(5).explain 的程式碼,並說明 Arel 產生的查詢。這允許檢查適當的索引和進一步的最佳化。

執行時間超過半秒的查詢會自動在開發模式中說明。當然,可以變更此閾值。

3.3 標籤記錄

在執行多使用者、多帳戶應用程式時,能夠依執行者篩選記錄會很有幫助。Active Support 中的 TaggedLogging 有助於準確地執行此操作,方法是以子網域、請求 ID 和任何其他有助於除錯此類應用程式的內容來蓋印記錄行。

4 文件

從 Rails 3.2 開始,Rails 指南適用於 Kindle 和 iPad、iPhone、Mac、Android 等的免費 Kindle 閱讀應用程式。

5 Railties

  • 僅在相依性檔案變更時重新載入類別,以加快開發速度。可以透過將 config.reload_classes_only_on_change 設定為 false 來關閉此功能。

  • 新的應用程式會在環境設定檔案中取得 config.active_record.auto_explain_threshold_in_seconds 旗標。在 development.rb 中的值為 0.5,在 production.rb 中已註解。在 test.rb 中沒有提及。

  • 新增 config.exceptions_app 以設定發生例外狀況時由 ShowException 中介軟體叫用的例外狀況應用程式。預設值為 ActionDispatch::PublicExceptions.new(Rails.public_path)

  • 新增一個 DebugExceptions 中介軟體,其中包含從 ShowExceptions 中介軟體提取的功能。

  • rake routes 中顯示已掛載引擎的路由。

  • 允許使用 config.railties_order 變更 railties 的載入順序,例如

    config.railties_order = [Blog::Engine, :main_app, :all]
    
  • Scaffold 為沒有內容的 API 請求傳回 204 No Content。這讓 scaffold 可以與 jQuery 開箱即用。

  • 更新 Rails::Rack::Logger 中介軟體,將 config.log_tags 中設定的任何標籤套用至 ActiveSupport::TaggedLogging。這讓您可以使用子網域和請求 ID 等偵錯資訊輕鬆地標記記錄行,這兩者對於偵錯多使用者生產應用程式非常有幫助。

  • rails new 的預設選項可以在 ~/.railsrc 中設定。您可以指定每次在主目錄中的 .railsrc 設定檔案中執行 rails new 時要使用的額外命令列引數。

  • destroy 新增別名 d。這也適用於引擎。

  • scaffold 和模型產生器上的屬性預設為字串。這允許以下操作:bin/rails g scaffold Post title body:text author

  • 允許 scaffold/model/migration 產生器接受 "index" 和 "uniq" 修飾符。例如,

    $ bin/rails g scaffold Post title:string:index author:uniq price:decimal{7,2}
    

    將會為 titleauthor 建立索引,後者會是唯一索引。某些型別(如 decimal)接受自訂選項。在範例中,price 將會是一個 decimal 欄位,其精確度和刻度分別設定為 7 和 2。

  • 已從預設的 Gemfile 中移除 turn gem。

  • 移除舊的 plugin 產生器 rails generate plugin,改用 rails plugin new 命令。

  • 移除舊的 config.paths.app.controller API,改用 config.paths["app/controller"]

5.1 已棄用的功能

  • Rails::Plugin 已棄用,將會在 Rails 4.0 中移除。請使用 gem 或 bundler 搭配路徑或 git 相依性,而不是將 plugin 加入至 vendor/plugins 中。

6 Action Mailer

  • 已將 mail 版本升級至 2.4.0。

  • 已移除自 Rails 3.0 起已棄用的舊 Action Mailer API。

7 Action Pack

7.1 Action Controller

  • ActiveSupport::Benchmarkable 設定為 ActionController::Base 的預設模組,如此 #benchmark 方法就能像以前一樣在 controller 內容中使用。

  • caches_page 中新增 :gzip 選項。預設選項可以使用 page_cache_compression 全域設定。

  • 當您使用 :only:except 條件指定 layout,但這些條件失敗時,Rails 現在會使用您的預設 layout(例如 "layouts/application")。

    class CarsController
      layout 'single_car', :only => :show
    end
    

    當請求進入 :show action 時,Rails 會使用 layouts/single_car,而當請求進入其他任何 action 時,則會使用 layouts/application (或 layouts/cars,如果存在)。

  • 如果提供 :as 選項,則 form_for 會變更為使用 #{action}_#{as} 作為 CSS 類別和 id。先前的版本使用 #{as}_#{action}

  • Active Record 模型上的 ActionController::ParamsWrapper 現在只會封裝已設定的 attr_accessible 屬性。如果未設定,則只會封裝類別方法 attribute_names 所傳回的屬性。這會修正透過將巢狀屬性加入至 attr_accessible 來封裝巢狀屬性的問題。

  • 每次 before callback 停止時,都會記錄 "Filter chain halted as CALLBACKNAME rendered or redirected"。

  • ActionDispatch::ShowExceptions 已重構。controller 負責選擇是否顯示例外狀況。您可以覆寫 controllers 中的 show_detailed_exceptions?,以指定哪些請求應提供錯誤的偵錯資訊。

  • Responders 現在會針對沒有回應主體的 API 請求傳回 204 No Content(如同新的 scaffold)。

  • ActionController::TestCase cookies 已重構。現在應該使用 cookies[] 為測試案例指派 cookies。

    cookies[:email] = 'user@example.com'
    get :index
    assert_equal 'user@example.com', cookies[:email]
    

    若要清除 cookies,請使用 clear

    cookies.clear
    get :index
    assert_nil cookies[:email]
    

    我們現在不再寫出 HTTP_COOKIE,且 cookie jar 會在請求之間保持持續性,因此如果您需要操作測試的環境,您需要在建立 cookie jar 之前執行此操作。

  • 如果未提供 :typesend_file 現在會從檔案副檔名猜測 MIME 型別。

  • 已新增 PDF、ZIP 和其他格式的 MIME 型別條目。

  • 允許 fresh_when/stale? 接受記錄,而不是選項雜湊。

  • 將遺失 CSRF token 的警告記錄層級從 :debug 變更為 :warn

  • Assets 應預設使用請求協定,如果沒有可用的請求,則預設為相對路徑。

7.1.1 已棄用的功能

  • 已棄用在其父系設定了明確 layout 的 controller 中隱含的 layout 查詢。

    class ApplicationController
      layout "application"
    end
    
    class PostsController < ApplicationController
    end
    

    在以上範例中,PostsController 將不再自動查詢 posts layout。如果您需要此功能,您可以從 ApplicationController 中移除 layout "application",或在 PostsController 中明確地將其設定為 nil

  • 已棄用 ActionController::UnknownAction,改用 AbstractController::ActionNotFound

  • 已棄用 ActionController::DoubleRenderError,改用 AbstractController::DoubleRenderError

  • 已棄用 method_missing,改用 action_missing 來處理遺失的 action。

  • 已棄用 ActionController#rescue_actionActionController#initialize_template_classActionController#assign_shortcuts

7.2 Action Dispatch

  • 新增 config.action_dispatch.default_charset,以設定 ActionDispatch::Response 的預設字元集。

  • 新增 ActionDispatch::RequestId 中介軟體,此中介軟體將會使唯一 X-Request-Id 標頭可供回應使用,並啟用 ActionDispatch::Request#uuid 方法。這讓追蹤堆疊中的端對端請求,並識別 Syslog 等混合記錄中的個別請求變得容易。

  • ShowExceptions 中介軟體現在接受例外狀況應用程式,該應用程式負責在應用程式失敗時呈現例外狀況。應用程式會使用 env["action_dispatch.exception"] 中的例外狀況複本和重寫為狀態碼的 PATH_INFO 來叫用。

  • 允許透過 railtie 設定 rescue 回應,如 config.action_dispatch.rescue_responses 中所示。

7.2.1 已棄用的功能

  • 已棄用在 controller 層級設定預設字元集的功能,請改用新的 config.action_dispatch.default_charset

7.3 Action View

  • 新增 button_tagActionView::Helpers::FormBuilder 的支援。此支援模擬 submit_tag 的預設行為。

    <%= form_for @post do |f| %>
      <%= f.button %>
    <% end %>
    
  • 日期 helpers 接受新的選項 :use_two_digit_numbers => true,該選項會使用前導零來呈現月份和日期的選取方塊,而不會變更各自的值。例如,這對於顯示 '2011-08-01' 等 ISO 8601 樣式的日期很有用。

  • 您可以為表單提供命名空間,以確保表單元素上的 id 屬性具有唯一性。命名空間屬性將會附加底線作為產生的 HTML id 的前置字元。

    <%= form_for(@offer, :namespace => 'namespace') do |f| %>
      <%= f.label :version, 'Version' %>:
      <%= f.text_field :version %>
    <% end %>
    
  • 限制 select_year 的選項數量為 1000。傳遞 :max_years_allowed 選項以設定您自己的限制。

  • content_tag_fordiv_for 現在可以接受記錄的集合。如果您在區塊中設定接收引數,則也會將記錄作為第一個引數產生。因此,您不需要執行以下操作:

    @items.each do |item|
      content_tag_for(:li, item) do
        Title: <%= item.title %>
      end
    end
    

    您可以執行以下操作:

    content_tag_for(:li, @items) do |item|
      Title: <%= item.title %>
    end
    
  • 新增 font_path helper 方法,該方法會計算 public/fonts 中字型 asset 的路徑。

7.3.1 已棄用的功能

  • 已棄用將格式或處理常式傳遞至 render :template 和類似方法,如 render :template => "foo.html.erb"。您可以改為直接提供 :handlers 和 :formats 作為選項:render :template => "foo", :formats => [:html, :js], :handlers => :erb

7.4 Sprockets

  • 新增組態選項 config.assets.logger,以控制 Sprockets 記錄。將其設定為 false 以關閉記錄,並設定為 nil 以預設為 Rails.logger

8 Active Record

  • 值為 'on' 和 'ON' 的布林欄位會轉換為 true。

  • timestamps 方法建立 created_atupdated_at 欄位時,預設會使其為不可為 null。

  • 已實作 ActiveRecord::Relation#explain

  • 已實作 ActiveRecord::Base.silence_auto_explain,這可讓使用者在區塊中選擇性地停用自動 EXPLAIN。

  • 已實作慢查詢的自動 EXPLAIN 記錄。新的組態參數 config.active_record.auto_explain_threshold_in_seconds 會決定哪些是慢查詢。將其設定為 nil 會停用此功能。預設值在開發模式中為 0.5,而在測試和生產模式中為 nil。Rails 3.2 支援 SQLite、MySQL (mysql2 轉接器) 和 PostgreSQL 中的此功能。

  • 新增 ActiveRecord::Base.store,以宣告簡單的單欄鍵/值儲存區。

    class User < ActiveRecord::Base
      store :settings, accessors: [ :color, :homepage ]
    end
    
    u = User.new(color: 'black', homepage: '37signals.com')
    u.color                          # Accessor stored attribute
    u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor
    
  • 新增僅針對給定範圍執行遷移的功能,這可讓您僅從一個引擎執行遷移(例如,從需要移除的引擎還原變更)。

    rake db:migrate SCOPE=blog
    
  • 從引擎複製的遷移現在會使用引擎的名稱來設定範圍,例如 01_create_posts.blog.rb

  • 已實作 ActiveRecord::Relation#pluck 方法,該方法會直接從基礎表格傳回欄位值陣列。這也適用於序列化的屬性。

    Client.where(:active => true).pluck(:id)
    # SELECT id from clients where active = 1
    
  • 產生的關聯方法會在個別的模組中建立,以允許覆寫和組合。對於名為 MyModel 的類別,模組名稱為 MyModel::GeneratedFeatureMethods。它會在 Active Model 中定義的 generated_attributes_methods 模組之後立即包含在模型類別中,因此關聯方法會覆寫同名的屬性方法。

  • 新增 ActiveRecord::Relation#uniq,以產生唯一查詢。

    Client.select('DISTINCT name')
    

    ..可以寫成

    Client.select(:name).uniq
    

    這也讓您可以在關係中還原唯一性

    Client.select(:name).uniq.uniq(false)
    
  • 支援 SQLite、MySQL 和 PostgreSQL 轉接器中的索引排序順序。

  • 允許關聯的 :class_name 選項除了字串之外還接受符號。這是為了避免讓新手感到困惑,並與其他選項(如 :foreign_key)已經允許符號或字串保持一致。

    has_many :clients, :class_name => :Client # Note that the symbol need to be capitalized
    
  • 在開發模式中,db:drop 也會卸載測試資料庫,以便與 db:create 對稱。

  • 當欄位已經使用不區分大小寫的定序時,不區分大小寫的唯一性驗證會避免在 MySQL 中呼叫 LOWER。

  • 交易固定裝置會徵用所有作用中的資料庫連線。您可以在不同的連線上測試模型,而無需停用交易固定裝置。

  • first_or_createfirst_or_create!first_or_initialize 方法新增至 Active Record。與舊的 find_or_create_by 動態方法相比,這是一種更好的方法,因為它更清楚哪些引數用於尋找記錄,以及哪些引數用於建立記錄。

    User.where(:first_name => "Scarlett").first_or_create!(:last_name => "Johansson")
    
  • 為 Active Record 物件新增 with_lock 方法,該方法會啟動交易、鎖定物件(悲觀式)並產生區塊。此方法會接受一個(選擇性)參數,並將其傳遞至 lock!

    這讓以下寫法成為可能

    class Order < ActiveRecord::Base
      def cancel!
        transaction do
          lock!
          # ... cancelling logic
        end
      end
    end
    

    如同

    class Order < ActiveRecord::Base
      def cancel!
        with_lock do
          # ... cancelling logic
        end
      end
    end
    

8.1 已棄用的功能

  • 已棄用執行緒中自動關閉連線的功能。例如,以下程式碼已棄用

    Thread.new { Post.find(1) }.join
    

    應變更為在執行緒結束時關閉資料庫連線

    Thread.new {
      Post.find(1)
      Post.connection.close
    }.join
    

    只有在其應用程式程式碼中產生執行緒的使用者才需要擔心此變更。

  • 已棄用 set_table_nameset_inheritance_columnset_sequence_nameset_primary_keyset_locking_column 方法。請改用指派方法。例如,請使用 self.table_name=,而不是 set_table_name

    class Project < ActiveRecord::Base
      self.table_name = "project"
    end
    

    或定義您自己的 self.table_name 方法

    class Post < ActiveRecord::Base
      def self.table_name
        "special_" + super
      end
    end
    
    Post.table_name # => "special_posts"
    

9 Active Model

  • 新增 ActiveModel::Errors#added?,以檢查是否已新增特定錯誤。

  • 新增使用 strict => true 定義嚴格驗證的功能,該功能在失敗時一律會引發例外狀況。

  • 提供 mass_assignment_sanitizer 作為一個簡單的 API 來取代 sanitizer 的行為。同時也支援 :logger (預設) 和 :strict 這兩種 sanitizer 行為。

9.1 已棄用

  • 已棄用 ActiveModel::AttributeMethods 中的 define_attr_method,因為它僅用於支援 Active Record 中類似 set_table_name 的方法,而這些方法本身也正在被棄用。

  • 已棄用 Model.model_name.partial_path,改用 model.to_partial_path

10 Active Resource

  • 重新導向回應:303 See Other 和 307 Temporary Redirect 現在的行為類似於 301 Moved Permanently 和 302 Found。

11 Active Support

  • 新增了 ActiveSupport:TaggedLogging,它可以包裹任何標準的 Logger 類別,以提供標籤功能。

    Logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
    
    Logger.tagged("BCX") { Logger.info "Stuff" }
    # Logs "[BCX] Stuff"
    
    Logger.tagged("BCX", "Jason") { Logger.info "Stuff" }
    # Logs "[BCX] [Jason] Stuff"
    
    Logger.tagged("BCX") { Logger.tagged("Jason") { Logger.info "Stuff" } }
    # Logs "[BCX] [Jason] Stuff"
    
  • DateTimeDateTime 中的 beginning_of_week 方法接受一個可選的參數,表示一週開始的日期。

  • ActiveSupport::Notifications.subscribed 提供在區塊執行時訂閱事件的功能。

  • 定義了新的方法 Module#qualified_const_defined?Module#qualified_const_getModule#qualified_const_set,它們與標準 API 中相應的方法類似,但接受限定的常數名稱。

  • 新增了 #deconstantize,它補充了 inflections 中的 #demodulize。這會移除限定常數名稱中最右邊的部分。

  • 新增了 safe_constantize,它會將字串轉換為常數,但如果該常數(或其一部分)不存在,則會返回 nil 而不是拋出例外。

  • 使用 Array#extract_options! 時,ActiveSupport::OrderedHash 現在被標記為可提取。

  • 新增了 Array#prepend 作為 Array#unshift 的別名,以及 Array#append 作為 Array#<< 的別名。

  • Ruby 1.9 中空白字串的定義已擴展到 Unicode 空白字元。此外,在 Ruby 1.8 中,表意文字空格 U`3000 被視為空白字元。

  • inflector 可以理解縮寫。

  • 新增了 Time#all_dayTime#all_weekTime#all_quarterTime#all_year 作為產生範圍的方式。

    Event.where(:created_at => Time.now.all_week)
    Event.where(:created_at => Time.now.all_day)
    
  • 新增了 instance_accessor: false 作為 Class#cattr_accessor 及其相關方法的選項。

  • 當給定一個接受帶 splat 參數的區塊時,ActiveSupport::OrderedHash 現在對 #each#each_pair 有不同的行為。

  • 新增了 ActiveSupport::Cache::NullStore,用於開發和測試。

  • 移除了 ActiveSupport::SecureRandom,改用標準程式庫中的 SecureRandom

11.1 已棄用

  • 已棄用 ActiveSupport::Base64,改用 ::Base64

  • 已棄用 ActiveSupport::Memoizable,改用 Ruby 的 memoization 模式。

  • Module#synchronize 已被棄用,沒有替代方法。請使用 ruby 標準程式庫中的 monitor。

  • 已棄用 ActiveSupport::MessageEncryptor#encryptActiveSupport::MessageEncryptor#decrypt

  • 已棄用 ActiveSupport::BufferedLogger#silence。如果您想在特定區塊中抑制日誌,請變更該區塊的日誌級別。

  • 已棄用 ActiveSupport::BufferedLogger#open_log。這個方法一開始就不應該是公開的。

  • ActiveSupport::BufferedLogger 自動為您的日誌檔案建立目錄的行為已被棄用。請確保在實例化之前為您的日誌檔案建立目錄。

  • 已棄用 ActiveSupport::BufferedLogger#auto_flushing。請像這樣設定底層檔案控制代碼的同步級別。或調整您的檔案系統。現在由 FS 快取控制刷新。

    f = File.open('foo.log', 'w')
    f.sync = true
    ActiveSupport::BufferedLogger.new f
    
  • 已棄用 ActiveSupport::BufferedLogger#flush。請設定檔案控制代碼的同步,或調整您的檔案系統。

12 貢獻者

請參閱 Rails 的完整貢獻者列表,了解許多人花了許多時間讓 Rails 成為現在穩定且強大的框架。向他們所有人致敬。

Rails 3.2 發行說明由 Vijay Dev 編寫。



回到頂端