v7.1.3.2
更多資訊請至 rubyonrails.org: 更多 Ruby on Rails

Ruby on Rails 3.2 發行說明

Rails 3.2 的重點

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

1 升級至 Rails 3.2

如果您正在升級現有應用程式,在開始之前,最好能有良好的測試涵蓋率。如果您尚未升級到 Rails 3.1,您也應該先升級到 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 供應寶石

Rails 現在在應用程式根目錄中使用 Gemfile 來決定你的應用程式啟動所需寶石。這個 GemfileBundler 寶石處理,然後安裝你的所有相依性。它甚至可以將所有相依性安裝在你的應用程式本機,讓它不依賴系統寶石。

更多資訊:Bundler 首頁

2.2 站在最前線

BundlerGemfile 讓凍結你的 Rails 應用程式變得像吃派一樣容易,使用新的專用 bundle 指令。如果你想直接從 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 附帶一個不錯的功能,它會說明由 Arel 產生的查詢,方法是在 ActiveRecord::Relation 中定義一個 explain 方法。例如,你可以執行類似 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 會傳回 204 無內容,以供沒有內容的 API 要求使用。這使得 scaffold 能夠直接與 jQuery 搭配使用。

  • 更新 Rails::Rack::Logger 中介軟體,以將 config.log_tags 中設定的任何標籤套用至 ActiveSupport::TaggedLogging。這使得為日誌列加上子網域和要求 ID 等偵錯資訊變得容易,這兩個資訊在偵錯多使用者製作應用程式時都很有幫助。

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

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

  • 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 建立索引,後者為唯一索引。某些類型(例如小數)接受自訂選項。在範例中,price 將會是小數欄位,精度和比例分別設定為 7 和 2。

  • 已從預設的 Gemfile 中移除 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 背景中提供,如同過去一般。

  • 已將 :gzip 選項加入 caches_page。預設選項可使用 page_cache_compression 全域設定。

  • 當您使用 :only:except 條件指定版面,且這些條件失敗時,Rails 現在將使用您的預設版面(例如「layouts/application」)。

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

    當要求進入 :show 動作時,Rails 將使用 layouts/single_car;當要求進入任何其他動作時,Rails 將使用 layouts/application(或 layouts/cars,如果存在)。

  • 如果提供 :as 選項,form_for 已變更為使用 #{action}_#{as} 作為 CSS 類別和 ID。較早的版本使用 #{as}_#{action}

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

  • 每次 before 回呼中斷時,都會記錄「Filter chain halted as CALLBACKNAME rendered or redirected」。

  • ActionDispatch::ShowExceptions 已重構。控制器負責選擇是否顯示例外。可以在控制器中覆寫 show_detailed_exceptions? 以指定哪些要求應在錯誤中提供偵錯資訊。

  • 回應器現在會針對沒有回應主體的 API 要求傳回 204 無內容(如新的架構中)。

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

    cookies[:email] = '[email protected]'
    get :index
    assert_equal '[email protected]', cookies[:email]
    

    若要清除 Cookie,請使用 clear

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

    我們現在不再寫出 HTTP_COOKIE,且 Cookie 儲存區在要求之間是持續的,因此,如果您需要為測試操作環境,您需要在建立 Cookie 儲存區之前進行操作。

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

  • 已新增 PDF、ZIP 及其他格式的 MIME 類型項目。

  • 允許 fresh_when/stale? 使用記錄,而非選項雜湊。

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

  • 資產預設應使用要求通訊協定,或在沒有可用要求時預設為相對路徑。

7.1.1 已過時

  • 已過時控制器中暗示的版面配置查詢,其父項已設定明確的版面配置

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

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

  • 已過時 ActionController::UnknownAction,改用 AbstractController::ActionNotFound

  • 已過時 ActionController::DoubleRenderError,改用 AbstractController::DoubleRenderError

  • 已棄用 method_missing,改為使用 action_missing 以處理遺失的動作。

  • 已棄用 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 設定救援回應,例如 config.action_dispatch.rescue_responses

7.2.1 已棄用

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

7.3 Action View

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

    <%= form_for @post do |f| %>
      <%= f.button %>
    <% end %>
    
  • 日期輔助程式接受新的選項 :use_two_digit_numbers => true,它會呈現月份和日期的選取方塊,並在前面加上零,而不變更各自的值。例如,這對於顯示 ISO 8601 格式的日期(例如「2011-08-01」)很有用。

  • 您可以為表單提供命名空間,以確保表單元素中 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 輔助程式方法,用於計算 public/fonts 中字型資源的路徑。

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 欄位時,預設會將它們設為不可為空值。

  • 實作 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,用於宣告單一欄位 key/value 儲存。

    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")
    
  • 新增 with_lock 方法到 Active Record 物件,它會開始一個交易,鎖定物件(悲觀的)並傳遞到區塊。此方法會接受一個(可選的)參數,並將它傳遞給 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 作為取代 sanitiser 行為的簡易 API。同時支援 :logger (預設) 和 :strict sanitiser 行為。

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 查看其他和 307 暫時重新導向現在的行為與 301 已永久搬移和 302 已找到相同。

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,它在變形中補充了 #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 被視為空白。

  • 變形器了解縮寫字。

  • 新增 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 和相關函式的選項。

  • 當給定一個以散列方式接受其參數的區塊時,ActiveSupport::OrderedHash 現在對 #each#each_pair 有不同的行為。

  • 新增 ActiveSupport::Cache::NullStore,供開發和測試使用。

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

11.1 已過時

  • ActiveSupport::Base64 已過時,改用 ::Base64

  • 已過時的 ActiveSupport::Memoizable,改用 Ruby 記憶模式。

  • Module#synchronize 已過時,沒有替換。請使用 Ruby 標準函式庫中的監視器。

  • 已過時的 ActiveSupport::MessageEncryptor#encryptActiveSupport::MessageEncryptor#decrypt

  • ActiveSupport::BufferedLogger#silence 已過時。如果您想要抑制特定區塊的記錄,請變更該區塊的記錄層級。

  • ActiveSupport::BufferedLogger#open_log 已過時。這個方法一開始就不應該公開。

  • ActiveSupport::BufferedLogger 自動建立日誌檔案目錄的行為已過時。請務必在建立執行個體之前建立日誌檔案的目錄。

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

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

12 個學分

請參閱 Rails 貢獻者完整清單,以了解許多人花費許多小時製作 Rails,使其成為穩定且強大的架構。向他們所有人致敬。

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

回饋

我們鼓勵您協助提升本指南的品質。

如果您發現任何錯字或事實錯誤,請協助我們修正。首先,您可以閱讀我們的 文件貢獻 部分。

您也可能會發現不完整或未更新的內容。請為 main 新增任何遺漏的文件。請務必先查看 Edge Guides,以驗證問題是否已在主分支中修正。查看 Ruby on Rails 指南準則,以了解風格和慣例。

如果您發現需要修正但無法自行修補的任何問題,請 開啟一個問題

最後但並非最不重要的一點是,我們非常歡迎在 官方 Ruby on Rails 論壇 上針對 Ruby on Rails 文件進行任何類型的討論。