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

Ruby on Rails 2.2 發行說明

Rails 2.2 提供了多項新功能和改良功能。此清單涵蓋了主要的升級,但不包含每個小錯誤修正和變更。如果您想查看所有內容,請查看 GitHub 上 Rails 主要儲存庫中的提交清單

隨著 Rails,2.2 標誌著Ruby on Rails 指南的推出,這是持續進行的Rails 指南黑客松的第一批成果。此網站將提供 Rails 主要功能的高品質文件。

1 基礎架構

Rails 2.2 是 Rails 基礎架構的重大版本,讓 Rails 保持運作並連接至世界其他地區。

1.1 國際化

Rails 2.2 提供一個簡單的國際化系統(或 i18n,對於那些打字打到累的人來說)。

1.2 與 Ruby 1.9 和 JRuby 相容

除了執行緒安全性之外,還有許多工作已完成,讓 Rails 能順利與 JRuby 和即將推出的 Ruby 1.9 搭配使用。由於 Ruby 1.9 是個變動目標,在邊緣 Ruby 上執行邊緣 Rails 仍然是碰運氣的提議,但 Rails 已準備好在後者發布時轉換至 Ruby 1.9。

2 文件

Rails 的內部文件,以程式碼註解的形式,已在多處獲得改善。此外,Ruby on Rails 指南專案是關於 Rails 主要元件資訊的權威來源。在首次正式發布時,指南頁面包括

總而言之,指南為初階和中階 Rails 開發人員提供了數萬字的指導。

如果您想在應用程式內部產生這些指南

$ rake doc:guides

這會將指南放入 Rails.root/doc/guides,你可以透過在喜愛的瀏覽器中開啟 Rails.root/doc/guides/index.html 立即開始瀏覽。

3 更佳的 HTTP 整合:開箱即用的 ETag 支援

支援 HTTP 標頭中的 ETag 和最後修改時間戳記表示 Rails 現在可以在收到對最近未修改資源的請求時傳回空回應。這可讓你檢查是否需要傳送回應。

class ArticlesController < ApplicationController
  def show_with_respond_to_block
    @article = Article.find(params[:id])

    # If the request sends headers that differs from the options provided to stale?, then
    # the request is indeed stale and the respond_to block is triggered (and the options
    # to the stale? call is set on the response).
    #
    # If the request headers match, then the request is fresh and the respond_to block is
    # not triggered. Instead, the default render will occur, which will check the last-modified
    # and etag headers and conclude that it only needs to send a "304 Not Modified" instead
    # of rendering the template.
    if stale?(:last_modified => @article.published_at.utc, :etag => @article)
      respond_to do |wants|
        # normal response processing
      end
    end
  end

  def show_with_implied_render
    @article = Article.find(params[:id])

    # Sets the response headers and checks them against the request, if the request is stale
    # (i.e. no match of either etag or last-modified), then the default render of the template happens.
    # If the request is fresh, then the default render will return a "304 Not Modified"
    # instead of rendering the template.
    fresh_when(:last_modified => @article.published_at.utc, :etag => @article)
  end
end

4 執行緒安全性

Rails 2.2 陸續推出讓 Rails 具備執行緒安全性的功能。根據你的網路伺服器基礎架構,這表示你可以使用較少的 Rails 記憶體副本處理更多請求,進而提升伺服器效能並更有效率地使用多核心。

若要在應用程式的生產模式中啟用多執行緒調度,請在 config/environments/production.rb 中新增下列程式碼列

config.threadsafe!

5 Active Record

這裡有兩項重大新增功能:交易遷移和合併資料庫交易。此外,還有新的(且更簡潔的)聯結表條件語法,以及許多較小的改善。

5.1 交易遷移

在過去,多步驟的 Rails 移轉一直是問題的來源。如果在移轉過程中發生錯誤,錯誤之前的步驟都已變更資料庫,而錯誤之後的步驟則不會套用。此外,移轉版本會儲存為已執行,這表示在修正問題後,無法透過 rake db:migrate:redo 重新執行。交易移轉透過將移轉步驟包裝在 DDL 交易中,來改變這種情況,如此一來,如果其中任何一個步驟失敗,整個移轉就會復原。在 Rails 2.2 中,交易移轉在 PostgreSQL 中預設支援。未來,此程式碼可延伸至其他資料庫類型,而 IBM 已將其延伸,以支援 DB2 介面卡。

5.2 連線池

連線池讓 Rails 能夠在連線池中分配資料庫要求,該連線池會成長到最大值(預設為 5,但您可以在 database.yml 中新增 pool 鍵來調整此值)。這有助於移除支援大量同時使用者的應用程式中的瓶頸。此外,有一個 wait_timeout,預設為 5 秒,然後放棄。如果您需要,ActiveRecord::Base.connection_pool 可讓您直接存取連線池。

development:
  adapter: mysql
  username: root
  database: sample_development
  pool: 10
  wait_timeout: 10

5.3 加入資料表條件的雜湊

您現在可以使用雜湊來指定加入資料表的條件。如果您需要查詢複雜的加入,這將會很有幫助。

class Photo < ActiveRecord::Base
  belongs_to :product
end

class Product < ActiveRecord::Base
  has_many :photos
end

# Get all products with copyright-free photos:
Product.all(:joins => :photos, :conditions => { :photos => { :copyright => false }})

5.4 新的動態尋找器

已新增兩組新的方法至 Active Record 的動態尋找器系列。

5.4.1 find_last_by_attribute

find_last_by_attribute 方法等於 Model.last(:conditions => {:attribute => value})

# Get the last user who signed up from London
User.find_last_by_city('London')

5.4.2 find_by_attribute!

find_by_attribute! 的新 bang!版本等於 Model.first(:conditions => {:attribute => value}) || raise ActiveRecord::RecordNotFound 如果找不到相符的記錄,這個方法會引發例外,而不是傳回 nil

# Raise ActiveRecord::RecordNotFound exception if 'Moby' hasn't signed up yet!
User.find_by_name!('Moby')

5.5 關聯尊重私人/受保護範圍

Active Record 關聯代理現在尊重代理物件上方法的範圍。先前(假設 User has_one :account)@user.account.private_method 會呼叫關聯 Account 物件上的私人方法。這在 Rails 2.2 中會失敗;如果您需要這個功能,您應該使用 @user.account.send(:private_method)(或將方法設為公開,而不是私人或受保護)。請注意,如果您覆寫 method_missing,您也應該覆寫 respond_to 以符合行為,讓關聯能正常運作。

5.6 其他 Active Record 變更

  • rake db:migrate:redo 現在接受一個選用的 VERSION,以針對特定遷移進行重做
  • 設定 config.active_record.timestamped_migrations = false 以讓遷移具有數字前綴,而不是 UTC 時間戳記。
  • 計數快取欄位(針對使用 :counter_cache => true 宣告的關聯)不再需要初始化為零。
  • ActiveRecord::Base.human_name 可提供模型名稱的國際化感知人道翻譯

6 Action Controller

在控制器方面,有幾個變更將有助於整理您的路由。路由引擎中也有一些內部變更,以降低複雜應用程式的記憶體使用量。

6.1 淺層路由巢狀

淺層路由巢狀提供了解決使用深度巢狀資源的眾所周知難題的方法。透過淺層巢狀,您只需要提供足夠的資訊,就能唯一識別您想要處理的資源。

map.resources :publishers, :shallow => true do |publisher|
  publisher.resources :magazines do |magazine|
    magazine.resources :photos
  end
end

這將啟用對(除其他外)這些路由的辨識

/publishers/1           ==> publisher_path(1)
/publishers/1/magazines ==> publisher_magazines_path(1)
/magazines/2            ==> magazine_path(2)
/magazines/2/photos     ==> magazines_photos_path(2)
/photos/3               ==> photo_path(3)

6.2 成員或集合路由的方法陣列

您現在可以提供一個新成員或集合路由的方法陣列。這消除了必須定義一個路由為接受任何動詞的煩惱,只要您需要它處理多個動詞即可。使用 Rails 2.2,這是一個合法的路由宣告

map.resources :photos, :collection => { :search => [:get, :post] }

6.3 具有特定動作的資源

預設情況下,當您使用 map.resources 來建立一個路由時,Rails 會為七個預設動作(索引、顯示、建立、新增、編輯、更新和刪除)產生路由。但這些路由中的每個路由都會佔用應用程式的記憶體,並導致 Rails 產生額外的路由邏輯。現在,您可以使用 :only:except 選項來微調 Rails 將為資源產生的路由。您可以提供單一動作、動作陣列或特殊的 :all:none 選項。這些選項會由巢狀資源繼承。

map.resources :photos, :only => [:index, :show]
map.resources :products, :except => :destroy

6.4 其他動作控制器變更

  • 現在,您可以輕鬆地顯示自訂錯誤頁面,以處理在路由請求時引發的例外狀況。
  • HTTP Accept 標頭現在預設為停用。您應該偏好使用格式化網址(例如 /customers/1.xml)來指出您想要的格式。如果您需要 Accept 標頭,您可以使用 config.action_controller.use_accept_header = true 將它們重新開啟。
  • 基準測試數字現在以毫秒為單位報告,而不是以極小的秒數為單位
  • Rails 現在支援僅限 HTTP 的 Cookie(並將其用於工作階段),這有助於減輕較新瀏覽器中的一些跨網站指令碼風險。
  • redirect_to 現在完全支援 URI 架構(因此,例如,您可以重新導向到 svn`ssh: URI)。
  • render 現在支援 :js 選項,以使用正確的 MIME 類型來呈現純粹的 JavaScript。
  • 請求偽造防護已加強,僅適用於 HTML 格式的內容請求。
  • 如果傳遞的參數為 nil,多型網址的行為會更合理。例如,使用 nil 日期呼叫 polymorphic_path([@project, @date, @area]) 會提供 project_area_path

7 Action View

  • javascript_include_tagstylesheet_link_tag 支援新的 :recursive 選項,可與 :all 搭配使用,以便您可以使用單一行程式碼載入整個檔案樹狀結構。
  • 包含的 Prototype JavaScript 函式庫已升級至版本 1.6.0.3。
  • RJS#page.reload 可透過 JavaScript 重新載入瀏覽器的目前位置
  • atom_feed 輔助程式現在採用 :instruct 選項,讓您可以插入 XML 處理指令。

8 Action Mailer

Action Mailer 現在支援郵件版面配置。您可以透過提供適當命名的版面配置,讓 HTML 電子郵件像瀏覽器中的檢視一樣漂亮 - 例如,CustomerMailer 類別預期使用 layouts/customer_mailer.html.erb

Action Mailer 現在提供對 GMail SMTP 伺服器的內建支援,方法是自動開啟 STARTTLS。這需要安裝 Ruby 1.8.7。

9 Active Support

Active Support 現在為 Rails 應用程式提供內建記憶化,each_with_object 方法、委派前綴支援,以及其他各種新的公用程式方法。

9.1 記憶化

記憶化是一種方法,初始化一次方法,然後將其值儲存起來重複使用。您可能在自己的應用程式中使用過這種模式

def full_name
  @full_name ||= "#{first_name} #{last_name}"
end

記憶化讓您可以用宣告方式處理此任務

extend ActiveSupport::Memoizable

def full_name
  "#{first_name} #{last_name}"
end
memoize :full_name

記憶化的其他功能包括 unmemoizeunmemoize_allmemoize_all,用於開啟或關閉記憶化。

9.2 each_with_object

each_with_object 方法提供 inject 的替代方案,使用從 Ruby 1.9 回移植的方法。它會反覆運算集合,將目前的元素和備忘傳遞到區塊中。

%w(foo bar).each_with_object({}) { |str, hsh| hsh[str] = str.upcase } # => {'foo' => 'FOO', 'bar' => 'BAR'}

主要貢獻者:Adam Keys

9.3 帶有前綴的委派

如果您委派一個類別的行為到另一個類別,您現在可以指定一個前綴,用於識別委派的方法。例如

class Vendor < ActiveRecord::Base
  has_one :account
  delegate :email, :password, :to => :account, :prefix => true
end

這將產生委派的方法 vendor#account_emailvendor#account_password。您也可以指定自訂的前綴

class Vendor < ActiveRecord::Base
  has_one :account
  delegate :email, :password, :to => :account, :prefix => :owner
end

這將產生委派的方法 vendor#owner_emailvendor#owner_password

主要貢獻者:Daniel Schierbeck

9.4 其他 Active Support 變更

  • ActiveSupport::Multibyte 的廣泛更新,包括 Ruby 1.9 相容性修正。
  • 新增 ActiveSupport::Rescuable 允許任何類別混合 rescue_from 語法。
  • DateTime 類別的 past?today?future?,用於簡化日期/時間比較。
  • Array#secondArray#fifth 作為 Array#[1]Array#[4] 的別名
  • Enumerable#many? 封裝 collection.size > 1
  • Inflector#parameterize 產生輸入的 URL 就緒版本,用於 to_param
  • Time#advance 辨識小數天和週,所以您可以執行 1.7.weeks.ago1.5.hours.since 等。
  • 內含的 TzInfo 函式庫已升級至版本 0.3.12。
  • ActiveSupport::StringInquirer 提供一個漂亮的方式來測試字串的相等性:ActiveSupport::StringInquirer.new("abc").abc? => true

10 Railties

在 Railties(Rails 本身的核心程式碼)中,最大的變更在於 config.gems 機制。

10.1 config.gems

為避免部署問題並讓 Rails 應用程式更為獨立,可以在 /vendor/gems 中放置 Rails 應用程式所需的所有 gem 的副本。此功能首次出現在 Rails 2.1,但在 Rails 2.2 中更具彈性且強大,可處理 gem 之間的複雜相依性。Rails 中的 gem 管理包含以下指令

  • config/environment.rb 檔案中的 config.gem _gem_name_
  • rake gems 列出所有設定的 gem,以及它們(及其相依性)是否已安裝、凍結或框架(框架 gem 是在執行 gem 相依性程式碼之前由 Rails 載入的 gem;此類 gem 無法凍結)
  • rake gems:install 將遺失的 gem 安裝到電腦
  • rake gems:unpack 將所需 gem 的副本放置到 /vendor/gems
  • rake gems:unpack:dependencies 將所需 gem 及其相依性的副本取得到 /vendor/gems
  • rake gems:build 建立任何遺失的原生擴充功能
  • rake gems:refresh_specs 將使用 Rails 2.1 建立的供應商寶石與 Rails 2.2 的儲存方式保持一致

您可以在命令列中指定 GEM=_gem_name_ 來解壓縮或安裝單一寶石。

10.2 其他 Railties 變更

  • 如果您是 Thin 網路伺服器的愛好者,您會很樂意知道 script/server 現在直接支援 Thin。
  • script/plugin install &lt;plugin&gt; -r &lt;revision&gt; 現在適用於基於 git 和基於 svn 的外掛程式。
  • script/console 現在支援 --debugger 選項
  • 在 Rails 原始碼中包含設定連續整合伺服器以建置 Rails 本身的說明
  • rake notes:custom ANNOTATION=MYFLAG 讓您可以列出自訂註解。
  • Rails.env 包裝在 StringInquirer 中,讓您可以執行 Rails.env.development?
  • 為了消除不建議使用的警告並適當地處理寶石相依性,Rails 現在需要 rubygems 1.3.1 或更高版本。

11 不建議使用

在此版本中,一些較舊的程式碼已不建議使用

  • Rails::SecretKeyGenerator 已被 ActiveSupport::SecureRandom 取代
  • render_component 已不建議使用。如果您需要此功能,可以使用 render_components 外掛程式
  • 已不建議在呈現部分時進行隱式區域指派。

    def partial_with_implicit_local_assignment
      @customer = Customer.new("Marcel")
      render :partial => "customer"
    end
    

    先前上述程式碼在部分「customer」內提供一個名為 customer 的區域變數。您現在應該透過 :locals hash 明確傳遞所有變數。

  • country_select 已移除。請參閱 不建議使用的頁面 以取得更多資訊和外掛程式替換。

  • ActiveRecord::Base.allow_concurrency 不再有任何效果。

  • ActiveRecord::Errors.default_error_messages 已棄用,建議使用 I18n.translate('activerecord.errors.messages')

  • 國際化的 %s%d 插值語法已棄用。

  • String#chars 已棄用,建議使用 String#mb_chars

  • 已棄用小數月或小數年的持續時間。請改用 Ruby 核心 DateTime 類別算術。

  • Request#relative_url_root 已棄用。請改用 ActionController::Base.relative_url_root

12 個學分

發行說明由 Mike Gunderloy 編譯

回饋

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

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

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

如果您發現需要修復的地方,但無法自行修補,請 開啟問題

最後,我們非常歡迎在 官方 Ruby on Rails 論壇 上針對 Ruby on Rails 文件進行任何討論。