更多資訊請參考 rubyonrails.org:

Ruby on Rails 2.3 發行說明

Rails 2.3 提供了許多新的和改進的功能,包括普遍的 Rack 整合、更新的 Rails Engines 支援、Active Record 的巢狀交易、動態和預設範圍、統一渲染、更有效率的路由、應用程式範本和靜默回溯。 此清單涵蓋了主要的升級,但不包括每個小的錯誤修正和變更。 如果您想查看所有內容,請查看 GitHub 上主要 Rails 儲存庫中的提交清單,或查看各個 Rails 組件的 CHANGELOG 檔案。

1 應用程式架構

Rails 應用程式的架構有兩個主要變更:完全整合 Rack 模組化網頁伺服器介面,以及更新的 Rails Engines 支援。

1.1 Rack 整合

Rails 現在已擺脫其 CGI 的過去,並在各處使用 Rack。 這需要並導致大量的內部變更(但如果您使用 CGI,請不用擔心;Rails 現在透過 Proxy 介面支援 CGI)。 不過,這是對 Rails 內部的重大變更。 升級到 2.3 後,您應該在本機環境和生產環境中進行測試。 一些需要測試的事項

  • 工作階段
  • Cookie
  • 檔案上傳
  • JSON/XML API

以下是與 Rack 相關的變更摘要

  • script/server 已切換為使用 Rack,這表示它支援任何與 Rack 相容的伺服器。 如果存在,script/server 也會取得 rackup 設定檔。 預設情況下,它會尋找 config.ru 檔案,但您可以使用 -c 開關覆寫此檔案。
  • FCGI 處理常式會透過 Rack。
  • ActionController::Dispatcher 維護自己的預設中介軟體堆疊。 中介軟體可以注入、重新排序和移除。 堆疊會在啟動時編譯成鏈。 您可以在 environment.rb 中設定中介軟體堆疊。
  • 已新增 rake middleware 工作來檢查中介軟體堆疊。 這對於偵錯中介軟體堆疊的順序很有用。
  • 已修改整合測試執行器,以執行整個中介軟體和應用程式堆疊。 這使得整合測試非常適合測試 Rack 中介軟體。
  • ActionController::CGIHandler 是 Rack 周圍的向後相容 CGI 包裝函式。 CGIHandler 旨在接收舊的 CGI 物件並將其環境資訊轉換為與 Rack 相容的形式。
  • 已移除 CgiRequestCgiResponse
  • 工作階段儲存區現在會延遲載入。 如果您在要求期間從未存取工作階段物件,則它永遠不會嘗試載入工作階段資料(剖析 Cookie、從記憶體快取載入資料或查詢 Active Record 物件)。
  • 您不再需要在測試中使用 CGI::Cookie.new 來設定 Cookie 值。 將 String 值指派給 request.cookies["foo"] 現在會如預期般設定 Cookie。
  • CGI::Session::CookieStore 已取代為 ActionController::Session::CookieStore
  • CGI::Session::MemCacheStore 已取代為 ActionController::Session::MemCacheStore
  • CGI::Session::ActiveRecordStore 已取代為 ActiveRecord::SessionStore
  • 您仍然可以使用 ActionController::Base.session_store = :active_record_store 變更您的工作階段儲存區。
  • 預設工作階段選項仍然使用 ActionController::Base.session = { :key => "..." } 設定。 不過,:session_domain 選項已重新命名為 :domain
  • 通常包裝您整個要求的互斥鎖已移至中介軟體 ActionController::Lock
  • ActionController::AbstractRequestActionController::Request 已統一。 新的 ActionController::Request 繼承自 Rack::Request。 這會影響測試要求中對 response.headers['type'] 的存取。 請改用 response.content_type
  • 如果已載入 ActiveRecord,則 ActiveRecord::QueryCache 中介軟體會自動插入到中介軟體堆疊中。 這個中介軟體會設定並清除每個要求的 Active Record 查詢快取。
  • Rails 路由器和控制器類別遵循 Rack 規格。 您可以使用 SomeController.call(env) 直接呼叫控制器。 路由器會將路由參數儲存在 rack.routing_args 中。
  • ActionController::Request 繼承自 Rack::Request
  • 請使用 config.action_controller.session = { :key => 'foo', ... 而不是 config.action_controller.session = { :session_key => 'foo', ...
  • 使用 ParamsParser 中介軟體會預先處理任何 XML、JSON 或 YAML 要求,以便稍後可以使用任何 Rack::Request 物件正常讀取它們。

1.2 更新的 Rails Engines 支援

經過幾個版本沒有升級後,Rails 2.3 為 Rails Engines(可以嵌入其他應用程式中的 Rails 應用程式)提供了一些新功能。 首先,引擎中的路由檔案現在會自動載入和重新載入,就像您的 routes.rb 檔案一樣(這也適用於其他外掛程式中的路由檔案)。 其次,如果您的外掛程式具有應用程式資料夾,則 app/[models|controllers|helpers] 會自動新增到 Rails 載入路徑。 引擎現在也支援新增視圖路徑,而且 Action Mailer 以及 Action View 也會使用引擎和其他外掛程式中的視圖。

2 文件

Ruby on Rails 指南專案已發布了幾個適用於 Rails 2.3 的額外指南。 此外,單獨的網站會維護 Edge Rails 指南的更新副本。 其他文件工作包括重新啟動 Rails wiki 和 Rails Book 的早期規劃。

3 Ruby 1.9.1 支援

無論您是在 Ruby 1.8 還是現在發布的 Ruby 1.9.1 上執行,Rails 2.3 都應該通過所有自己的測試。 不過,您應該注意,移至 1.9.1 需要檢查您所依賴的所有資料介面卡、外掛程式和其他程式碼是否與 Ruby 1.9.1 相容,以及 Rails 核心是否相容。

4 Active Record

Active Record 在 Rails 2.3 中獲得了許多新功能和錯誤修正。 重點包括巢狀屬性、巢狀交易、動態和預設範圍以及批次處理。

4.1 巢狀屬性

Active Record 現在可以直接更新巢狀模型上的屬性,前提是您告知它要這樣做

class Book < ActiveRecord::Base
  has_one :author
  has_many :pages

  accepts_nested_attributes_for :author, :pages
end

開啟巢狀屬性可啟用許多功能:自動(且不可分割)儲存記錄及其關聯的子記錄、子記錄感知驗證以及巢狀表單支援(稍後討論)。

您也可以使用 :reject_if 選項指定透過巢狀屬性新增的任何新記錄的需求

accepts_nested_attributes_for :author,
  :reject_if => proc { |attributes| attributes['name'].blank? }

4.2 巢狀交易

Active Record 現在支援巢狀交易,這是一個備受期待的功能。現在你可以撰寫像這樣的程式碼:

User.transaction do
  User.create(:username => 'Admin')
  User.transaction(:requires_new => true) do
    User.create(:username => 'Regular')
    raise ActiveRecord::Rollback
  end
end

User.find(:all)  # => Returns only Admin

巢狀交易允許你回滾內部交易,而不會影響外部交易的狀態。如果你希望交易是巢狀的,你必須明確地添加 :requires_new 選項;否則,巢狀交易只會變成父交易的一部分 (如同目前在 Rails 2.2 的情況)。在底層,巢狀交易是使用儲存點 (savepoints),因此即使在沒有真正巢狀交易的資料庫上也能支援。還有一點額外的處理,以使這些交易在測試期間能與交易 fixture 良好配合。

4.3 動態範圍 (Dynamic Scopes)

你可能知道 Rails 中的動態查找器 (dynamic finders) (允許你即時創建像 find_by_color_and_flavor 這樣的方法),以及具名範圍 (named scopes) (允許你將可重複使用的查詢條件封裝成友好的名稱,如 currently_active)。現在,你可以擁有動態範圍方法。其概念是組合語法,允許即時篩選方法鏈接。例如:

Order.scoped_by_customer_id(12)
Order.scoped_by_customer_id(12).find(:all,
  :conditions => "status = 'open'")
Order.scoped_by_customer_id(12).scoped_by_status("open")

使用動態範圍無需定義任何東西:它們就能直接運作。

4.4 預設範圍 (Default Scopes)

Rails 2.3 將引入與具名範圍相似的預設範圍的概念,但它適用於模型內的所有具名範圍或查找方法。例如,你可以寫 default_scope :order => 'name ASC',這樣任何時候你從該模型檢索記錄時,它們都會按名稱排序 (當然,除非你覆蓋此選項)。

4.5 批次處理 (Batch Processing)

現在你可以使用 find_in_batches 從 Active Record 模型中處理大量的記錄,而不會對記憶體造成過大的壓力。

Customer.find_in_batches(:conditions => {:active => true}) do |customer_group|
  customer_group.each { |customer| customer.update_account_balance! }
end

你可以將大多數 find 選項傳遞給 find_in_batches。但是,你不能指定記錄返回的順序 (它們總是按主鍵的升序返回,主鍵必須是整數),也不能使用 :limit 選項。相反,請使用 :batch_size 選項 (預設為 1000) 來設定每個批次返回的記錄數量。

新的 find_each 方法提供了 find_in_batches 的封裝,它返回單個記錄,而查找本身是以批次 (預設為 1000) 進行的。

Customer.find_each do |customer|
  customer.update_account_balance!
end

請注意,你應該僅將此方法用於批次處理:對於少量記錄 (少於 1000),你應該直接使用常規的查找方法與你自己的迴圈。

4.6 回呼的多重條件 (Multiple Conditions for Callbacks)

在使用 Active Record 回呼時,你現在可以在同一個回呼上組合 :if:unless 選項,並將多個條件作為陣列提供。

before_save :update_credit_rating, :if => :active,
  :unless => [:admin, :cash_only]
  • 主要貢獻者:L. Caviola

4.7 使用 having 進行查找 (Find with having)

Rails 現在在 find 上 (以及在 has_manyhas_and_belongs_to_many 關聯上) 具有 :having 選項,用於篩選分組查找中的記錄。正如那些具有深厚 SQL 背景的人所知,這允許根據分組結果進行篩選。

developers = Developer.find(:all, :group => "salary",
  :having => "sum(salary) > 10000", :select => "salary")

4.8 重新連接 MySQL 連線 (Reconnecting MySQL Connections)

MySQL 在其連線中支援重新連接標誌 - 如果設定為 true,則客戶端會在失去連線的情況下嘗試重新連接到伺服器,然後才會放棄。你現在可以在 database.yml 中為 MySQL 連線設定 reconnect = true,以從 Rails 應用程式獲得此行為。預設值為 false,因此現有應用程式的行為不會改變。

4.9 其他 Active Record 變更

  • 從為 has_and_belongs_to_many 預載生成的 SQL 中刪除了一個額外的 AS,使其在某些資料庫上更好地運作。
  • 當遇到現有記錄時,ActiveRecord::Base#new_record? 現在返回 false 而不是 nil
  • 修復了某些 has_many :through 關聯中引用表格名稱的錯誤。
  • 你現在可以為 updated_at 時間戳記指定特定的時間戳記:cust = Customer.create(:name => "ABC Industries", :updated_at => 1.day.ago)
  • 在失敗的 find_by_attribute! 呼叫上提供更好的錯誤訊息。
  • Active Record 的 to_xml 支援透過新增 :camelize 選項獲得更多彈性。
  • 修復了從 before_updatebefore_create 取消回呼的錯誤。
  • 新增了透過 JDBC 測試資料庫的 Rake 任務。
  • validates_length_of 將使用帶有 :in:within 選項的自訂錯誤訊息 (如果提供了)。
  • 範圍選擇上的計數現在可以正常運作,因此你可以執行類似 Account.scoped(:select => "DISTINCT credit_limit").count 的操作。
  • ActiveRecord::Base#invalid? 現在作為 ActiveRecord::Base#valid? 的相反作用。

5 Action Controller

在此版本中,Action Controller 推出了對渲染的一些重大變更,以及路由和其他領域的改進。

5.1 統一渲染 (Unified Rendering)

ActionController::Base#render 在決定要渲染的內容時變得更加智慧。現在你可以直接告訴它要渲染什麼,並期望得到正確的結果。在舊版本的 Rails 中,你通常需要提供明確的資訊才能進行渲染。

render :file => '/tmp/random_file.erb'
render :template => 'other_controller/action'
render :action => 'show'

現在在 Rails 2.3 中,你可以直接提供要渲染的內容

render '/tmp/random_file.erb'
render 'other_controller/action'
render 'show'
render :show

Rails 會根據要渲染的內容中是否有前導斜線、內嵌斜線或完全沒有斜線,來選擇檔案、範本或動作。請注意,在渲染動作時,你也可以使用符號而不是字串。其他渲染樣式 (:inline:text:update:nothing:json:xml:js) 仍然需要明確的選項。

5.2 重新命名應用程式控制器 (Application Controller Renamed)

如果你是那些一直對 application.rb 的特殊命名方式感到困擾的人之一,那麼歡呼吧!它已在 Rails 2.3 中重構為 application_controller.rb。此外,還有一個新的 Rake 任務,rake rails:update:application_controller 來自動執行此操作 - 它將作為正常 rake rails:update 流程的一部分執行。

5.3 HTTP Digest 身份驗證支援

Rails 現在內建支援 HTTP Digest 身份驗證。要使用它,你需要使用一個區塊呼叫 authenticate_or_request_with_http_digest,該區塊會返回使用者的密碼 (然後對其進行雜湊並與傳輸的憑證進行比較)

class PostsController < ApplicationController
  Users = {"dhh" => "secret"}
  before_filter :authenticate

  def secret
    render :text => "Password Required!"
  end

  private
  def authenticate
    realm = "Application"
    authenticate_or_request_with_http_digest(realm) do |name|
      Users[name]
    end
  end
end

5.4 更有效率的路由 (More Efficient Routing)

Rails 2.3 中有一些重要的路由變更。formatted_ 路由助手已被移除,取而代之的是直接將 :format 作為選項傳遞。這將任何資源的路由生成過程減少了 50% - 並且可以節省大量的記憶體 (在大型應用程式上最多可節省 100MB)。如果你的程式碼使用 formatted_ 助手,它仍然會在目前的時間內運作 - 但此行為已過時,如果你使用新的標準重寫這些路由,你的應用程式將更有效率。另一個重大變更是在 Rails 中,現在支援多個路由檔案,而不僅僅是 routes.rb。你可以隨時使用 RouteSet#add_configuration_file 來引入更多路由 - 而無需清除目前載入的路由。雖然此變更對於 Engines 最有用,但你可以在任何需要分批載入路由的應用程式中使用它。

5.5 基於 Rack 的延遲載入 Session

一個重大的變更將 Action Controller Session 儲存的基礎推到了 Rack 層級。這涉及程式碼中的大量工作,儘管它應該對你的 Rails 應用程式完全透明 (作為一個額外的好處,一些關於舊 CGI Session 處理器的棘手修補程式被刪除了)。然而,由於一個簡單的原因,它仍然很重要:非 Rails 的 Rack 應用程式可以存取與你的 Rails 應用程式相同的 Session 儲存處理器 (因此可以存取相同的 Session)。此外,Session 現在是延遲載入的 (與框架其餘部分的載入改進一致)。這意味著如果你不想要 Session,你不再需要明確停用 Session;只要不參考它們,它們就不會載入。

5.6 MIME 類型處理變更

Rails 中處理 MIME 類型的程式碼有一些變更。首先,MIME::Type 現在實作了 =~ 運算子,當你需要檢查是否有同義的類型時,會使事情更加簡潔

if content_type && Mime::JS =~ content_type
  # do something cool
end

Mime::JS =~ "text/javascript"        => true
Mime::JS =~ "application/javascript" => true

另一個變更是在各種位置檢查 JavaScript 時,框架現在使用 Mime::JS,使其能乾淨地處理這些替代方案。

5.7 最佳化 respond_to

在 Rails-Merb 團隊合併後的初步成果中,Rails 2.3 針對 respond_to 方法進行了一些最佳化,這個方法當然在許多 Rails 應用程式中被大量使用,以允許你的控制器根據傳入請求的 MIME 類型來格式化不同的結果。在消除對 method_missing 的呼叫並經過一些效能分析和調整後,我們看到使用簡單的 respond_to 在三種格式之間切換時,每秒處理的請求數量提高了 8%。最棒的是什麼?完全不需要修改您的應用程式碼,就能利用此加速優勢。

5.8 改善的快取效能

Rails 現在會針對從遠端快取儲存讀取的內容,保留一個每個請求的本機快取,減少不必要的讀取並提高網站效能。雖然這項工作最初僅限於 MemCacheStore,但它適用於任何實作了所需方法的遠端儲存。

5.9 本地化視圖

Rails 現在可以根據您設定的語系提供本地化的視圖。例如,假設您有一個 Posts 控制器,其中包含一個 show 動作。預設情況下,它會渲染 app/views/posts/show.html.erb。但是如果您設定 I18n.locale = :da,它會渲染 app/views/posts/show.da.html.erb。如果沒有本地化的範本,則會使用未裝飾的版本。Rails 還包括 I18n#available_localesI18n::SimpleBackend#available_locales,它們會傳回目前 Rails 專案中可用的翻譯陣列。

此外,您可以使用相同的方案來本地化 public 目錄中的 rescue 檔案:例如,public/500.da.htmlpublic/404.en.html 也能運作。

5.10 部分翻譯範圍

翻譯 API 的變更使得在 partial 中編寫鍵值翻譯變得更容易且減少重複。如果您從 people/index.html.erb 範本中呼叫 translate(".foo"),您實際上會呼叫 I18n.translate("people.index.foo")。如果您的鍵值沒有在前面加上句點,那麼 API 就不會限定範圍,就像之前一樣。

5.11 其他 Action Controller 變更

  • ETag 處理已稍微清理過:當回應沒有主體或使用 send_file 發送檔案時,Rails 現在會跳過發送 ETag 標頭。
  • 對於使用手機進行大量流量的網站來說,Rails 檢查 IP 欺騙可能會造成困擾,因為它們的代理伺服器通常沒有正確設定。如果您是這種情況,您現在可以設定 ActionController::Base.ip_spoofing_check = false 來完全停用檢查。
  • ActionController::Dispatcher 現在實作了自己的 middleware 堆疊,您可以透過執行 rake middleware 來查看。
  • Cookie sessions 現在具有持久的 session 識別碼,與伺服器端儲存具有 API 相容性。
  • 您現在可以使用符號作為 send_filesend_data:type 選項,例如:send_file("fabulous.png", :type => :png)
  • map.resources:only:except 選項不再由巢狀資源繼承。
  • 綁定的 memcached 客戶端已更新至 1.6.4.99 版。
  • expires_instale?fresh_when 方法現在接受 :public 選項,使其能與代理快取良好運作。
  • :requirements 選項現在可以正確地處理額外的 RESTful 成員路由。
  • 淺層路由現在可以正確地處理命名空間。
  • polymorphic_url 在處理具有不規則複數名稱的物件時,能有更好的表現。

6 Action View

Rails 2.3 中的 Action View 包含了巢狀模型表單、對 render 的改進、日期選擇輔助器的更靈活提示,以及資產快取的加速等等。

6.1 巢狀物件表單

假設父模型接受子物件的巢狀屬性(如 Active Record 章節中所討論),您可以使用 form_forfield_for 來建立巢狀表單。這些表單可以巢狀任意深度,讓您在單個視圖上編輯複雜的物件階層,而無需過多的程式碼。例如,給定這個模型

class Customer < ActiveRecord::Base
  has_many :orders

  accepts_nested_attributes_for :orders, :allow_destroy => true
end

您可以在 Rails 2.3 中編寫此視圖

<% form_for @customer do |customer_form| %>
  <div>
    <%= customer_form.label :name, 'Customer Name:' %>
    <%= customer_form.text_field :name %>
  </div>

  <!-- Here we call fields_for on the customer_form builder instance.
   The block is called for each member of the orders collection. -->
  <% customer_form.fields_for :orders do |order_form| %>
    <p>
      <div>
        <%= order_form.label :number, 'Order Number:' %>
        <%= order_form.text_field :number %>
      </div>

  <!-- The allow_destroy option in the model enables deletion of
   child records. -->
      <% unless order_form.object.new_record? %>
        <div>
          <%= order_form.label :_delete, 'Remove:' %>
          <%= order_form.checkbox :_delete %>
        </div>
      <% end %>
    </p>
  <% end %>

  <%= customer_form.submit %>
<% end %>

6.2 Partial 的智慧渲染

多年來,render 方法變得越來越聰明,現在更是如此。如果您有一個物件或集合以及一個適當的 partial,而且命名一致,您現在可以直接渲染物件,事情就會運作。例如,在 Rails 2.3 中,這些渲染呼叫將在您的視圖中運作(假設合理的命名)

# Equivalent of render :partial => 'articles/_article',
# :object => @article
render @article

# Equivalent of render :partial => 'articles/_article',
# :collection => @articles
render @articles

6.3 日期選擇輔助器的提示

在 Rails 2.3 中,您可以為各種日期選擇輔助器(date_selecttime_selectdatetime_select)提供自訂提示,就像您可以使用集合選擇輔助器一樣。您可以為各種元件提供提示字串或個別提示字串的雜湊。您也可以將 :prompt 設定為 true 來使用自訂的通用提示

select_datetime(DateTime.now, :prompt => true)

select_datetime(DateTime.now, :prompt => "Choose date and time")

select_datetime(DateTime.now, :prompt =>
  {:day => 'Choose day', :month => 'Choose month',
   :year => 'Choose year', :hour => 'Choose hour',
   :minute => 'Choose minute'})

6.4 AssetTag 時間戳記快取

您可能很熟悉 Rails 將時間戳記新增至靜態資產路徑作為「快取清除器」的做法。這有助於確保當您在伺服器上變更影像和樣式表等內容時,不會從使用者的瀏覽器快取中提供過時的副本。您現在可以使用 Action View 的 cache_asset_timestamps 設定選項來修改此行為。如果您啟用快取,那麼 Rails 會在第一次提供資產時計算時間戳記,並儲存該值。這表示提供靜態資產的(昂貴)檔案系統呼叫會減少,但也表示您無法在伺服器執行時修改任何資產,並期望客戶端能擷取到變更。

6.5 資產主機作為物件

資產主機在 edge Rails 中變得更加靈活,能夠將資產主機宣告為特定物件,該物件會回應呼叫。這讓您可以在資產託管中實作所需的任何複雜邏輯。

6.6 grouped_options_for_select 輔助方法

Action View 已經有一堆輔助器來協助產生 select 控制項,但現在又多了一個:grouped_options_for_select。這個輔助器接受字串陣列或雜湊,並將它們轉換為以 optgroup 標籤包裝的 option 標籤字串。例如

grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]],
  "Cowboy Hat", "Choose a product...")

傳回

<option value="">Choose a product...</option>
<optgroup label="Hats">
  <option value="Baseball Cap">Baseball Cap</option>
  <option selected="selected" value="Cowboy Hat">Cowboy Hat</option>
</optgroup>

6.7 表單選擇輔助器的 disabled 選項標籤

表單選擇輔助器(例如 selectoptions_for_select)現在支援 :disabled 選項,該選項可以接受單個值或值陣列,以便在產生的標籤中停用

select(:post, :category, Post::CATEGORIES, :disabled => 'private')

傳回

<select name="post[category]">
<option>story</option>
<option>joke</option>
<option>poem</option>
<option disabled="disabled">private</option>
</select>

您也可以使用匿名函式在執行階段決定將從集合中選取和/或停用哪些選項

options_from_collection_for_select(@product.sizes, :name, :id, :disabled => lambda{|size| size.out_of_stock?})

6.8 關於範本載入的注意事項

Rails 2.3 包含針對任何特定環境啟用或停用快取範本的功能。快取範本可提升速度,因為它們在渲染時不會檢查新的範本檔案,但也表示您無法在不重新啟動伺服器的情況下「即時」替換範本。

在大多數情況下,您會希望在生產環境中開啟範本快取,這可以透過在您的 production.rb 檔案中進行設定來完成

config.action_view.cache_template_loading = true

此行會在新的 Rails 2.3 應用程式中預設為您產生。如果您是從較舊版本的 Rails 升級,Rails 會預設在生產環境和測試環境中快取範本,但在開發環境中則不會。

6.9 其他 Action View 變更

  • CSRF 保護的權杖產生已簡化;現在 Rails 使用 ActiveSupport::SecureRandom 產生的簡單隨機字串,而不是與 session ID 混淆。
  • auto_link 現在可以正確地將選項(例如 :target:class)套用到產生的電子郵件連結。
  • autolink 輔助器已重構,使其稍微不雜亂且更直覺。
  • 即使 URL 中有多個查詢參數,current_page? 現在也能正常運作。

7 Active Support

Active Support 有一些有趣的變更,包括引入 Object#try

7.1 Object#try

很多人都採用使用 try() 來嘗試對物件進行操作的概念。這在視圖中特別有用,您可以透過撰寫類似 <%= @person.try(:name) %> 的程式碼來避免 nil 檢查。現在它已經直接整合到 Rails 中。在 Rails 中實作時,它會針對私有方法引發 NoMethodError,並且如果物件為 nil,則始終傳回 nil

7.2 Object#tap Backport

Object#tapRuby 1.9 和 1.8.7 的新增功能,它類似於 Rails 一直以來擁有的 returning 方法:它會產生一個區塊,然後傳回所產生的物件。Rails 現在包含程式碼,讓這也可以在較舊版本的 Ruby 中使用。

7.3 XMLmini 的可交換解析器

Active Support 中對 XML 解析的支援已變得更加靈活,允許您換入不同的解析器。預設情況下,它使用標準的 REXML 實作,但是您可以輕鬆地為自己的應用程式指定更快的 LibXML 或 Nokogiri 實作,前提是您已安裝了適當的 gem

XmlMini.backend = 'LibXML'

7.4 TimeWithZone 的小數秒

TimeTimeWithZone 類別包含一個 xmlschema 方法,以 XML 友善的字串傳回時間。從 Rails 2.3 開始,TimeWithZone 支援相同的引數,用於指定傳回字串的小數秒部分中的位數,這與 Time 相同

Time.zone.now.xmlschema(6) # => "2009-01-16T13:00:06.13653Z"

7.5 JSON 鍵值引號

如果您查看 "json.org" 網站上的規範,您會發現 JSON 結構中的所有鍵值都必須是字串,而且必須用雙引號括起來。從 Rails 2.3 開始,我們在這裡做了正確的事情,即使是數字鍵值也是如此。

7.6 其他 Active Support 變更

  • 您可以使用 Enumerable#none? 來檢查是否沒有任何元素符合提供的區塊。
  • 如果您使用的是 Active Support 的 委派,新的 :allow_nil 選項可讓您在目標物件為 nil 時傳回 nil,而不是引發例外。
  • ActiveSupport::OrderedHash:現在實作了 each_keyeach_value
  • ActiveSupport::MessageEncryptor 提供了一種簡單的方法來加密資訊,以便儲存在不受信任的位置(例如 cookie)。
  • Active Support 的 from_xml 不再依賴 XmlSimple。取而代之的是,Rails 現在包含了它自己的 XmlMini 實作,僅具備它所需的功能。這讓 Rails 可以省去一直以來攜帶的 XmlSimple 捆綁副本。
  • 如果你將一個私有方法記憶化(memoize),結果現在會是私有的。
  • String#parameterize 接受一個可選的分隔符:"Quick Brown Fox".parameterize('_') => "quick_brown_fox"
  • number_to_phone 現在接受 7 位數的電話號碼。
  • ActiveSupport::Json.decode 現在可以處理 \u0000 風格的跳脫序列。

8 Railties

除了上面涵蓋的 Rack 變更之外,Railties(Rails 本身的核心程式碼)還進行了許多重大變更,包括 Rails Metal、應用程式範本和靜默回溯追蹤。

8.1 Rails Metal

Rails Metal 是一種新的機制,可在您的 Rails 應用程式中提供超快的端點。Metal 類別繞過路由和 Action Controller,以提供原始速度(當然,代價是犧牲 Action Controller 中的所有功能)。這是建立在最近所有基礎工作的基礎上,使 Rails 成為一個具有公開中介軟體堆疊的 Rack 應用程式。Metal 端點可以從您的應用程式或外掛程式中載入。

8.2 應用程式範本

Rails 2.3 包含了 Jeremy McAnally 的 rg 應用程式產生器。這表示我們現在在 Rails 中內建了基於範本的應用程式產生功能;如果您有一組您在每個應用程式中都包含的外掛程式(以及許多其他用例),您只需設定一次範本,並在執行 rails 指令時重複使用它。還有一個 rake 任務可以將範本套用到現有的應用程式。

$ rake rails:template LOCATION=~/template.rb

這會將範本中的變更疊加在專案已有的任何程式碼之上。

8.3 更安靜的回溯追蹤

在 thoughtbot 的 Quiet Backtrace 外掛程式的基礎上,該外掛程式允許您有選擇性地從 Test::Unit 回溯追蹤中移除行,Rails 2.3 在核心中實作了 ActiveSupport::BacktraceCleanerRails::BacktraceCleaner。這支援過濾器(對回溯追蹤行執行基於正則表達式的替換)和靜音器(完全移除回溯追蹤行)。Rails 會自動新增靜音器來消除新應用程式中最常見的雜訊,並建立一個 config/backtrace_silencers.rb 檔案來保存您自己的新增項目。此功能還能從回溯追蹤中的任何 gem 更漂亮地列印。

8.4 使用延遲載入/自動載入縮短開發模式的啟動時間

為了確保只有在實際需要時才將 Rails(及其依賴項)的程式碼載入到記憶體中,做了大量的工作。核心框架 - Active Support、Active Record、Action Controller、Action Mailer 和 Action View - 現在都使用 autoload 來延遲載入它們的個別類別。這項工作應有助於減少記憶體佔用並提高 Rails 的整體效能。

您也可以指定(透過使用新的 preload_frameworks 選項)是否應在啟動時自動載入核心程式庫。預設值為 false,以便 Rails 逐段自動載入自己,但在某些情況下,您仍然需要一次載入所有內容 - Passenger 和 JRuby 都希望看到所有 Rails 一起載入。

8.5 rake gem 任務重寫

已大幅修改各種 rake gem 任務的內部結構,以使系統在各種情況下都能更好地工作。gem 系統現在知道開發和執行時依賴項之間的區別,具有更強大的解壓縮系統,在查詢 gem 的狀態時提供更好的資訊,並且在從頭開始建立時不太容易出現「雞生蛋還是蛋生雞」的依賴問題。還有修復程式可以解決在 JRuby 下使用 gem 命令的問題,以及解決嘗試引入已 vendor 的 gem 外部副本的依賴項的問題。

8.6 其他 Railties 變更

  • 已更新和擴充更新 CI 伺服器以建置 Rails 的說明。
  • 內部 Rails 測試已從 Test::Unit::TestCase 切換到 ActiveSupport::TestCase,並且 Rails 核心需要 Mocha 才能進行測試。
  • 預設的 environment.rb 檔案已簡化。
  • dbconsole 指令碼現在允許您使用全數字密碼而不會當機。
  • Rails.root 現在會傳回一個 Pathname 物件,這表示您可以直接將其與 join 方法一起使用,以清理使用 File.join 的現有程式碼
  • 預設情況下,不再在每個 Rails 應用程式中產生 /public 中處理 CGI 和 FCGI 分發的各種檔案(如果您需要在執行 rails 指令時新增 --with-dispatchers,或稍後使用 rake rails:update:generate_dispatchers 新增它們,您仍然可以取得它們)。
  • Rails 指南已從 AsciiDoc 轉換為 Textile 標記。
  • 已稍微清理 scaffolded 檢視和控制器。
  • script/server 現在接受 --path 引數,以從特定路徑掛載 Rails 應用程式。
  • 如果遺失任何設定的 gem,gem rake 任務將跳過載入大部分環境。這應可解決許多「雞生蛋還是蛋生雞」的問題,其中 rake gems:install 因為遺失 gem 而無法執行。
  • gem 現在只解壓縮一次。這修復了 gem(例如 hoe)的問題,這些 gem 的檔案是以唯讀權限打包的。

9 已棄用

在此版本中,一些較舊的程式碼已棄用

  • 如果您是少數(相當罕見)以依賴檢查器、收割機和產生器指令碼的方式部署的 Rails 開發人員之一,則需要知道這些指令碼不再包含在 Rails 核心中。如果您需要它們,您可以透過 irs_process_scripts 外掛程式取得副本。
  • render_component 在 Rails 2.3 中從「已棄用」變為「不存在」。如果您仍然需要它,您可以安裝 render_component 外掛程式
  • 已移除對 Rails 元件的支援。
  • 如果您是過去習慣執行 script/performance/request 以根據整合測試查看效能的人員之一,則需要學習一個新技巧:該指令碼現在已從 Rails 核心中移除。您可以安裝一個新的 request_profiler 外掛程式來恢復完全相同的功能。
  • ActionController::Base#session_enabled? 已棄用,因為現在會延遲載入工作階段。
  • protect_from_forgery:digest:secret 選項已棄用,並且不起作用。
  • 已移除一些整合測試輔助程式。response.headers["Status"]headers["Status"] 將不再傳回任何內容。Rack 不允許在其傳回標頭中出現「Status」。但是,您仍然可以使用 statusstatus_message 輔助程式。response.headers["cookie"]headers["cookie"] 將不再傳回任何 CGI Cookie。您可以檢查 headers["Set-Cookie"] 以查看原始 Cookie 標頭,或使用 cookies 輔助程式來取得傳送至用戶端的 Cookie 雜湊。
  • formatted_polymorphic_url 已棄用。請改用帶有 :formatpolymorphic_url
  • ActionController::Response#set_cookie 中的 :http_only 選項已重新命名為 :httponly
  • to_sentence:connector:skip_last_comma 選項已由 :words_connector:two_words_connector:last_word_connector 選項取代。
  • 使用空的 file_field 控制項張貼 multipart 表單過去會將空字串提交到控制器。現在,由於 Rack 的 multipart 分析器與舊 Rails 分析器之間的差異,它會提交一個 nil。

10 貢獻者

版本說明由 Mike Gunderloy 編譯。此版本的 Rails 2.3 版本說明是根據 Rails 2.3 的 RC2 編譯的。



回到頂端