更多資訊請參考 rubyonrails.org:

Ruby on Rails 3.1 發行說明

Rails 3.1 的重點

  • 串流
  • 可逆轉的遷移
  • 資產管道
  • jQuery 作為預設的 JavaScript 函式庫

這些發行說明僅涵蓋主要變更。若要了解各種錯誤修正和變更,請參閱變更記錄或查看 GitHub 上主要 Rails 儲存庫中的 commit 列表

1 升級至 Rails 3.1

如果您要升級現有的應用程式,最好先做好完善的測試涵蓋。您也應該先升級到 Rails 3,如果您尚未升級,並在嘗試更新到 Rails 3.1 之前,確認您的應用程式仍然按照預期執行。然後留意以下變更

1.1 Rails 3.1 至少需要 Ruby 1.8.7

Rails 3.1 需要 Ruby 1.8.7 或更高版本。已正式停止支援所有先前的 Ruby 版本,您應儘早升級。Rails 3.1 也與 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.2 在您的應用程式中更新哪些內容

以下變更旨在將您的應用程式升級到 Rails 3.1.3,這是 Rails 的最新 3.1.x 版本。

1.2.1 Gemfile

對您的 Gemfile 進行以下變更。

gem "rails", "= 3.1.3"
gem "mysql2"

# Needed for the new asset pipeline
group :assets do
  gem "sass-rails",   "~> 3.1.5"
  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"

1.2.2 config/application.rb

  • 資產管道需要以下新增內容

    config.assets.enabled = true
    config.assets.version = '1.0'
    
  • 如果您的應用程式使用 "/assets" 路由作為資源,您可能需要變更用於資產的前置詞以避免衝突

    # Defaults to '/assets'
    config.assets.prefix = '/asset-files'
    

1.2.3 config/environments/development.rb

  • 移除 RJS 設定 config.action_view.debug_rjs = true

  • 如果您啟用資產管道,請新增以下內容。

    # Do not compress assets
    config.assets.compress = false
    
    # Expands the lines which load the assets
    config.assets.debug = true
    

1.2.4 config/environments/production.rb

  • 同樣地,以下大部分變更都是針對資產管道。您可以在資產管道指南中閱讀更多相關資訊。

    # 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
    

1.2.5 config/environments/test.rb

# Configure static asset server for tests with Cache-Control for performance
config.serve_static_assets = true
config.static_cache_control = "public, max-age=3600"

1.2.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
    

1.2.7 移除視圖中資產輔助方法的 :cache 和 :concat 選項

  • 使用資產管道時,不再使用 :cache 和 :concat 選項,請從您的視圖中刪除這些選項。

2 建立 Rails 3.1 應用程式

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

2.1 供應商化 Gems

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

更多資訊:- bundler 首頁

2.2 走在最前沿

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

$ rails new myapp --edge

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

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

3 Rails 架構變更

3.1 資產管道

Rails 3.1 的主要變更是資產管道。它使 CSS 和 JavaScript 成為一等公民,並啟用適當的組織,包括在外掛程式和引擎中使用。

資產管道由 Sprockets 提供支援,並在資產管道指南中涵蓋。

3.2 HTTP 串流

HTTP 串流是 Rails 3.1 中的另一項新變更。這讓瀏覽器可以在伺服器仍在產生回應時下載您的樣式表和 JavaScript 檔案。這需要 Ruby 1.9.2,是選擇性加入的,並且也需要 Web 伺服器的支援,但流行的 NGINX 和 Unicorn 組合已準備好利用它。

3.3 預設的 JS 函式庫現在是 jQuery

jQuery 是 Rails 3.1 隨附的預設 JavaScript 函式庫。但是,如果您使用 Prototype,則可以輕鬆切換。

$ rails new myapp -j prototype

3.4 身分識別映射

Active Record 在 Rails 3.1 中具有身分識別映射。身分識別映射會保留先前實例化的記錄,並在再次存取時傳回與記錄相關聯的物件。身分識別映射是根據每個請求建立的,並在請求完成時清除。

Rails 3.1 預設關閉身分識別映射。

4 Railties

  • jQuery 是新的預設 JavaScript 函式庫。

  • jQuery 和 Prototype 不再是供應商化的,現在由 jquery-railsprototype-rails gem 提供。

  • 應用程式產生器接受一個選項 -j,它可以是任意字串。如果傳遞「foo」,則會將 gem「foo-rails」新增至 Gemfile,並且應用程式 JavaScript 資訊清單需要「foo」和「foo_ujs」。目前只有「prototype-rails」和「jquery-rails」存在,並透過資產管道提供這些檔案。

  • 除非指定 --skip-gemfile--skip-bundle,否則產生應用程式或外掛程式會執行 bundle install

  • 控制器和資源產生器現在會自動產生資產存根(可以使用 --skip-assets 關閉)。如果這些函式庫可用,這些存根將使用 CoffeeScript 和 Sass。

  • 在 Ruby 1.9 上執行時,Scaffold 和應用程式產生器會使用 Ruby 1.9 風格的雜湊。若要產生舊式雜湊,可以傳遞 --old-style-hash

  • Scaffold 控制器產生器會建立 JSON 的格式區塊,而不是 XML。

  • Active Record 記錄會導向 STDOUT,並在主控台中內嵌顯示。

  • 新增 config.force_ssl 設定,這會載入 Rack::SSL 中介軟體,並強制所有請求都透過 HTTPS 通訊協定進行。

  • 新增 rails plugin new 命令,這會產生一個 Rails 外掛程式,其中包含 gemspec、測試和用於測試的虛擬應用程式。

  • Rack::EtagRack::ConditionalGet 新增至預設的中介軟體堆疊。

  • Rack::Cache 新增至預設的中介軟體堆疊。

  • 引擎已收到重大更新 - 您可以將它們掛載到任何路徑、啟用資產、執行產生器等。

5 Action Pack

5.1 Action Controller

  • 如果無法驗證 CSRF 權杖的真確性,則會發出警告。

  • 在控制器中指定 force_ssl,以強制瀏覽器透過 HTTPS 通訊協定傳輸該特定控制器的資料。若要限制特定動作,可以使用 :only:except

  • config.filter_parameters 中指定的敏感查詢字串參數現在會從記錄中的請求路徑中篩除。

  • 現在,對於 to_param 方法回傳 nil 的 URL 參數,會從查詢字串中移除。

  • 新增了 ActionController::ParamsWrapper 來將參數包裝成巢狀的雜湊,並且預設會在新的應用程式中為 JSON 請求啟用。這可以在 config/initializers/wrap_parameters.rb 中自訂。

  • 新增了 config.action_controller.include_all_helpers。預設情況下,ActionController::Base 中會執行 helper :all,這會預設包含所有 helpers。將 include_all_helpers 設定為 false 將會只包含 application_helper 以及對應於 controller 的 helper(例如 foo_controller 的 foo_helper)。

  • url_for 和具名的 URL helpers 現在接受 :subdomain:domain 作為選項。

  • 新增了 Base.http_basic_authenticate_with,可以使用單一類別方法呼叫來進行簡單的 http 基本驗證。

    class PostsController < ApplicationController
      USER_NAME, PASSWORD = "dhh", "secret"
    
      before_filter :authenticate, :except => [ :index ]
    
      def index
        render :text => "Everyone can see me!"
      end
    
      def edit
        render :text => "I'm only accessible if you know the password"
      end
    
      private
        def authenticate
          authenticate_or_request_with_http_basic do |user_name, password|
            user_name == USER_NAME && password == PASSWORD
          end
        end
    end
    

    ..現在可以寫成

    class PostsController < ApplicationController
      http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index
    
      def index
        render :text => "Everyone can see me!"
      end
    
      def edit
        render :text => "I'm only accessible if you know the password"
      end
    end
    
  • 新增了串流支援,您可以使用以下方式啟用它:

    class PostsController < ActionController::Base
      stream
    end
    

    您可以使用 :only:except 將其限制於某些動作。請閱讀 ActionController::Streaming 的文件以獲取更多資訊。

  • 重新導向路由方法現在也接受一個選項雜湊,這個雜湊只會更改相關 URL 的部分,或者接受一個回應呼叫的物件,允許重新使用重新導向。

5.2 Action Dispatch

  • config.action_dispatch.x_sendfile_header 現在預設為 nil,並且 config/environments/production.rb 不會為其設定任何特定的值。這允許伺服器通過 X-Sendfile-Type 來設定它。

  • ActionDispatch::MiddlewareStack 現在使用組合而不是繼承,並且不再是一個陣列。

  • 新增了 ActionDispatch::Request.ignore_accept_header 來忽略 accept headers。

  • Rack::Cache 加入了預設的堆疊。

  • 將 etag 的責任從 ActionDispatch::Response 移到了 middleware 堆疊。

  • 依賴 Rack::Session stores API 以獲得在 Ruby 世界中更高的相容性。這是不相容的回溯變更,因為 Rack::Session 期望 #get_session 接受四個參數,並且需要 #destroy_session 而不是簡單的 #destroy

  • 樣板查詢現在會進一步向上搜尋繼承鏈。

5.3 Action View

  • form_tag 新增了一個 :authenticity_token 選項,以進行自訂處理或通過傳遞 :authenticity_token => false 來省略 token。

  • 建立了 ActionView::Renderer,並為 ActionView::Context 指定了一個 API。

  • Rails 3.1 中禁止就地 SafeBuffer 變異。

  • 新增了 HTML5 button_tag helper。

  • file_field 會自動將 :multipart => true 加入到封閉的表單中。

  • 新增了一個方便的慣用語,可以從選項的 :data 雜湊中在 tag helpers 中產生 HTML5 data-* 屬性。

    tag("div", :data => {:name => 'Stephen', :city_state => %w(Chicago IL)})
    # => <div data-name="Stephen" data-city-state="[&quot;Chicago&quot;,&quot;IL&quot;]" />
    

鍵會變成 dasherized。值會被 JSON 編碼,除了字串和符號。

  • csrf_meta_tag 已重新命名為 csrf_meta_tags,並為了向後相容性而將 csrf_meta_tag 設定為別名。

  • 舊的樣板處理器 API 已被棄用,新的 API 僅要求樣板處理器回應呼叫。

  • rhtml 和 rxml 最終從樣板處理器中移除。

  • config.action_view.cache_template_loading 已被帶回,允許決定是否應快取樣板。

  • 提交表單 helper 不再產生 id "object_name_id"。

  • 允許 FormHelper#form_for:method 指定為直接選項,而不是通過 :html 雜湊。例如:form_for(@post, remote: true, method: :delete) 而不是 form_for(@post, remote: true, html: { method: :delete })

  • 提供了 JavaScriptHelper#j() 作為 JavaScriptHelper#escape_javascript() 的別名。這取代了 JSON gem 使用 JavaScriptHelper 在樣板中新增的 Object#j() 方法。

  • 允許在日期時間選擇器中使用 AM/PM 格式。

  • auto_link 已從 Rails 中移除,並提取到 rails_autolink gem

6 Active Record

  • 新增了一個類別方法 pluralize_table_names 來單數化/複數化個別模型的表名稱。先前只能通過 ActiveRecord::Base.pluralize_table_names 為所有模型全域設定。

    class User < ActiveRecord::Base
      self.pluralize_table_names = false
    end
    
  • 新增了區塊設定單數關聯的屬性。在實例初始化後,將會呼叫該區塊。

    class User < ActiveRecord::Base
      has_one :account
    end
    
    user.build_account{ |a| a.credit_limit = 100.0 }
    
  • 新增了 ActiveRecord::Base.attribute_names 來回傳屬性名稱的列表。如果模型是抽象的或者表格不存在,這將會回傳一個空的陣列。

  • CSV Fixtures 已被棄用,並且在 Rails 3.2.0 中將會移除支援。

  • ActiveRecord#newActiveRecord#createActiveRecord#update_attributes 都接受第二個雜湊作為選項,該選項允許您指定在賦予屬性時要考慮的角色。這是建立在 Active Model 新的批次賦值功能之上的。

    class Post < ActiveRecord::Base
      attr_accessible :title
      attr_accessible :title, :published_at, :as => :admin
    end
    
    Post.new(params[:post], :as => :admin)
    
  • default_scope 現在可以接受一個區塊、lambda 或任何其他回應呼叫以進行延遲求值的物件。

  • 預設範圍現在會在最後可能的時間點進行評估,以避免產生隱式包含預設範圍的範圍,然後無法通過 Model.unscoped 來擺脫的問題。

  • PostgreSQL 配接器僅支援 PostgreSQL 8.2 版及更高版本。

  • ConnectionManagement 中間件已變更為在 rack body 已刷新後清理連接池。

  • 在 Active Record 上新增了一個 update_column 方法。這個新方法會更新物件上的指定屬性,跳過驗證和回呼。建議使用 update_attributesupdate_attribute,除非您確定您不想執行任何回呼,包括修改 updated_at 欄位。它不應在新紀錄上呼叫。

  • 具有 :through 選項的關聯現在可以使用任何關聯作為 through 或 source 關聯,包括其他具有 :through 選項和 has_and_belongs_to_many 關聯的關聯。

  • 現在可以通過 ActiveRecord::Base.connection_config 存取目前資料庫連接的設定。

  • 除非同時提供限制和偏移量,否則會從 COUNT 查詢中移除限制和偏移量。

    People.limit(1).count           # => 'SELECT COUNT(*) FROM people'
    People.offset(1).count          # => 'SELECT COUNT(*) FROM people'
    People.limit(1).offset(1).count # => 'SELECT COUNT(*) FROM people LIMIT 1 OFFSET 1'
    
  • ActiveRecord::Associations::AssociationProxy 已被分割。現在有一個 Association 類別(和子類別)負責操作關聯,然後有一個單獨的薄包裝器,稱為 CollectionProxy,它代理集合關聯。這防止了命名空間污染,分離了關注點,並且將允許進一步的重構。

  • 單數關聯(has_onebelongs_to)不再具有代理,而僅回傳相關的記錄或 nil。這表示您不應使用未記載的方法,例如 bob.mother.create - 請改用 bob.create_mother

  • 支援 has_many :through 關聯上的 :dependent 選項。由於歷史和實際原因,:delete_allassociation.delete(*records) 所使用的預設刪除策略,儘管對於常規的 has_many 來說,預設策略是 :nullify。此外,只有當 source 反射是 belongs_to 時,這才能起作用。對於其他情況,您應直接修改 through 關聯。

  • has_and_belongs_to_manyhas_many :throughassociation.destroy 行為已變更。從現在開始,關聯上的 'destroy' 或 'delete' 將被視為表示「擺脫連結」,而不是(必然)「擺脫相關的紀錄」。

  • 先前,has_and_belongs_to_many.destroy(*records) 會銷毀紀錄本身。它不會刪除連接表格中的任何紀錄。現在,它會刪除連接表格中的紀錄。

  • 先前,has_many_through.destroy(*records) 會銷毀紀錄本身,以及連接表格中的紀錄。[注意:情況並非總是如此;先前版本的 Rails 只會刪除紀錄本身。] 現在,它只會銷毀連接表格中的紀錄。

  • 請注意,此變更在某種程度上是不相容的回溯變更,但很遺憾,在變更之前沒有辦法「棄用」它。進行此變更是為了使不同類型的關聯之間「銷毀」或「刪除」的意義保持一致。如果您希望銷毀紀錄本身,則可以執行 records.association.each(&:destroy)

  • :bulk => true 選項新增到 change_table,以使用單一 ALTER 語句來變更在區塊中定義的所有 schema 變更。

    change_table(:users, :bulk => true) do |t|
      t.string :company_name
      t.change :birthdate, :datetime
    end
    
  • 移除了存取 has_and_belongs_to_many 連接表格上屬性的支援。需要使用 has_many :through

  • has_onebelongs_to 關聯新增了 create_association! 方法。

  • 遷移現在是可逆的,這表示 Rails 將會找出如何反轉您的遷移。要使用可逆的遷移,只需定義 change 方法即可。

    class MyMigration < ActiveRecord::Migration
      def change
        create_table(:horses) do |t|
          t.column :content, :text
          t.column :remind_at, :datetime
        end
      end
    end
    
  • 有些事情無法自動為您反轉。如果您知道如何反轉這些事情,則應在您的遷移中定義 updown。如果您在 change 中定義了無法反轉的內容,則在向下遷移時將會引發 IrreversibleMigration 異常。

  • 遷移現在使用實例方法,而不是類別方法

    class FooMigration < ActiveRecord::Migration
      def up # Not self.up
        # ...
      end
    end
    
  • 從模型和建構式遷移產生器(例如,add_name_to_users)產生的遷移檔案,會使用可逆遷移的 change 方法,而不是普通的 updown 方法。

  • 移除了在關聯上插值字串 SQL 條件的支援。相反,應使用 proc。

    has_many :things, :conditions => 'foo = #{bar}'          # before
    has_many :things, :conditions => proc { "foo = #{bar}" } # after
    

    在 proc 內部,self 是關聯的所有者物件,除非您正在急切載入關聯,在這種情況下,self 是關聯所在的類別。

    您可以在 proc 內加入任何「正常」條件,因此以下內容也將起作用

    has_many :things, :conditions => proc { ["foo = ?", bar] }
    
  • 先前 has_and_belongs_to_many 關聯上的 :insert_sql:delete_sql 允許您呼叫 'record' 來取得正在插入或刪除的記錄。現在會將其作為參數傳遞給 proc。

  • 新增了 ActiveRecord::Base#has_secure_password (通過 ActiveModel::SecurePassword),以使用 BCrypt 加密和加鹽來封裝最簡單的密碼使用。

    # Schema: User(name:string, password_digest:string, password_salt:string)
    class User < ActiveRecord::Base
      has_secure_password
    end
    
  • 當模型產生時,針對 belongs_toreferences 資料欄位,預設會加入 add_index

  • 設定 belongs_to 物件的 id 將會更新對該物件的參照。

  • ActiveRecord::Base#dupActiveRecord::Base#clone 的語意已變更,使其更接近一般的 Ruby dup 和 clone 語意。

  • 呼叫 ActiveRecord::Base#clone 將會產生記錄的淺層複製,包括複製凍結狀態。不會呼叫任何回呼函數。

  • 呼叫 ActiveRecord::Base#dup 將會複製記錄,包括呼叫 after initialize 勾點。凍結狀態不會被複製,並且所有關聯都會被清除。一個被複製的記錄將會針對 new_record? 返回 true,擁有一個 nil 的 id 欄位,且可儲存。

  • 查詢快取現在可與預處理語句一起使用。應用程式不需要任何變更。

7 Active Model

  • attr_accessible 接受一個選項 :as 來指定角色。

  • InclusionValidatorExclusionValidatorFormatValidator 現在接受一個選項,它可以是 proc、lambda,或任何回應 call 的物件。此選項將會使用目前的記錄作為引數來呼叫,並針對 InclusionValidatorExclusionValidator 返回一個回應 include? 的物件,以及針對 FormatValidator 返回一個正規表示式物件。

  • 新增 ActiveModel::SecurePassword 以封裝使用 BCrypt 加密和加鹽的簡單密碼用法。

  • ActiveModel::AttributeMethods 允許根據需要定義屬性。

  • 新增選擇性啟用和停用觀察器的支援。

  • 不再支援替代的 I18n 命名空間查找。

8 Active Resource

  • 所有請求的預設格式已變更為 JSON。如果您想繼續使用 XML,您需要在類別中設定 self.format = :xml。例如:

    class User < ActiveResource::Base
      self.format = :xml
    end
    

9 Active Support

  • ActiveSupport::Dependencies 如果在 load_missing_constant 中找到現有的常數,現在會引發 NameError

  • 新增一個新的報告方法 Kernel#quietly,它可以靜音 STDOUTSTDERR

  • 新增 String#inquiry 作為將字串轉換為 StringInquirer 物件的便利方法。

  • 新增 Object#in? 以測試物件是否包含在另一個物件中。

  • LocalCache 策略現在是一個真實的中介軟體類別,不再是匿名類別。

  • 引入 ActiveSupport::Dependencies::ClassCache 類別來保存對可重新載入類別的參照。

  • 已重構 ActiveSupport::Dependencies::Reference 以直接利用新的 ClassCache

  • 在 Ruby 1.8 中,將 Range#cover? 作為 Range#include? 的別名反向移植。

  • 在 Date/DateTime/Time 中新增 weeks_agoprev_week

  • ActiveSupport::Dependencies.remove_unloadable_constants! 新增 before_remove_const 回呼。

棄用

  • ActiveSupport::SecureRandom 已被棄用,建議使用 Ruby 標準函式庫中的 SecureRandom

10 致謝

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

Rails 3.1 版本說明由 Vijay Dev 編寫。



回到頂部