1 基礎架構
Rails 2.2 對於維持 Rails 順暢運作並與世界其他地方連線的基礎架構而言,是一個重要的發行版本。
1.1 國際化
Rails 2.2 提供一個簡單的國際化系統(或 i18n,對於那些厭倦輸入的人)。
- 主要貢獻者:Rails i18 團隊
- 更多資訊
1.2 與 Ruby 1.9 和 JRuby 的相容性
除了執行緒安全性之外,還做了許多工作來使 Rails 與 JRuby 和即將推出的 Ruby 1.9 良好運作。由於 Ruby 1.9 是一個不斷變化的目標,因此在 edge Ruby 上執行 edge Rails 仍然是一個碰運氣的命題,但 Rails 已準備好在後者發佈時轉換到 Ruby 1.9。
2 文件
Rails 的內部文件,以程式碼註解的形式,在許多地方都得到了改進。此外,Ruby on Rails 指南專案是主要 Rails 元件資訊的權威來源。在其首次正式發行中,「指南」頁面包含
- Rails 入門
- Rails 資料庫遷移
- Active Record 關聯
- Active Record 查詢介面
- Rails 中的佈局與渲染
- Action View 表單輔助方法
- Rails 路由從外而內
- Action Controller 概觀
- Rails 快取
- Rails 應用程式測試指南
- 保護 Rails 應用程式安全
- 偵錯 Rails 應用程式
- 建立 Rails 外掛程式的基礎
總而言之,「指南」為初級和中級 Rails 開發人員提供了數萬字的指導。
如果您想在本機應用程式內產生這些指南
$ rake doc:guides
這會將指南放入 Rails.root/doc/guides
中,您可以立即開始瀏覽,方法是在您最愛的瀏覽器中開啟 Rails.root/doc/guides/index.html
。
- 來自 Xavier Noria 和 Hongli Lai 的主要貢獻。
- 更多資訊
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 具備執行緒安全性所做的工作正在 Rails 2.2 中推出。根據您的 Web 伺服器基礎架構,這表示您可以使用較少記憶體中的 Rails 副本來處理更多要求,從而提高伺服器效能並更高地利用多核心。
若要啟用應用程式生產模式中的多執行緒分派,請在您的 config/environments/production.rb
中加入下列這一行
config.threadsafe!
5 Active Record
這裡有兩個主要的添加項目要討論:交易式資料庫遷移和集區資料庫交易。聯結表格條件也有一個新的(而且更簡潔的)語法,以及一些較小的改進。
5.1 交易式資料庫遷移
從歷史上看,多步驟的 Rails 資料庫遷移一直是問題的根源。如果在資料庫遷移期間發生錯誤,則錯誤之前的所有內容都會變更資料庫,而錯誤之後的所有內容都不會套用。此外,遷移版本會儲存為已執行,這表示在您修正問題後,它無法透過 rake db:migrate:redo
簡單地重新執行。交易式資料庫遷移透過將遷移步驟包裝在 DDL 交易中來改變這種情況,因此如果其中任何一個失敗,則會還原整個遷移。在 Rails 2.2 中,PostgreSQL 開箱即用支援交易式資料庫遷移。程式碼可以擴充到未來其他資料庫類型 - IBM 已經將其擴充為支援 DB2 配接器。
- 主要貢獻者:Adam Wiggins
- 更多資訊
5.2 連線池
連線池可讓 Rails 在資料庫連線集區中分散資料庫要求,該集區將成長到最大大小(預設為 5,但您可以將 pool
金鑰新增至您的 database.yml
以調整此設定)。這有助於移除支援許多並行使用者的應用程式中的瓶頸。還有一個 wait_timeout
,預設值為 5 秒,然後才會放棄。如果您需要,ActiveRecord::Base.connection_pool
可讓您直接存取集區。
development:
adapter: mysql
username: root
database: sample_development
pool: 10
wait_timeout: 10
- 主要貢獻者:Nick Sieger
- 更多資訊
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')
- 主要貢獻者:Emilio Tagua
5.4.2 find_by_attribute!
find_by_attribute!
的新驚嘆號版本等同於 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')
- 主要貢獻者:Josh Susser
5.5 關聯尊重 Private/Protected 範圍
Active Record 關聯代理現在會尊重代理物件上方法的範圍。先前(假設 User 具有 has_one :account)@user.account.private_method
會在相關聯的 Account 物件上呼叫 private 方法。這在 Rails 2.2 中會失敗;如果您需要此功能,則應使用 @user.account.send(:private_method)
(或將方法設為 public 而不是 private 或 protected)。請注意,如果您要覆寫 method_missing
,您也應該覆寫 respond_to
以比對行為,以便關聯正常運作。
- 主要貢獻者:Adam Milligan
- 更多資訊
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)
- 主要貢獻者:S. Brent Faulkner
- 更多資訊
6.2 成員或集合路由的方法陣列
你現在可以為新的成員或集合路由提供方法陣列。這消除了當你需要處理多個動詞時,必須將路由定義為接受任何動詞的惱人情況。在 Rails 2.2 中,這是一個合法的路由宣告。
map.resources :photos, :collection => { :search => [:get, :post] }
- 主要貢獻者:Brennan Dunn
6.3 具有特定動作的資源
預設情況下,當你使用 map.resources
建立路由時,Rails 會為七個預設動作(index、show、create、new、edit、update 和 destroy)產生路由。但是,這些路由中的每一個都會佔用你的應用程式記憶體,並導致 Rails 產生額外的路由邏輯。現在,你可以使用 :only
和 :except
選項來微調 Rails 將為資源產生的路由。你可以提供單一動作、動作陣列或特殊的 :all
或 :none
選項。這些選項會被巢狀資源繼承。
map.resources :photos, :only => [:index, :show]
map.resources :products, :except => :destroy
- 主要貢獻者:Tom Stuart
6.4 其他 Action Controller 變更
- 你現在可以輕鬆地為路由請求時引發的例外情況顯示自訂錯誤頁面。
- HTTP Accept 標頭現在預設為停用。你應該優先使用格式化的 URL(例如
/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,多態 URL 的行為會更加合理。例如,使用 nil 日期呼叫
polymorphic_path([@project, @date, @area])
將會得到project_area_path
。
7 Action View
javascript_include_tag
和stylesheet_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 現在透過自動開啟 STARTTLS,提供對 GMail SMTP 伺服器的內建支援。這需要安裝 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
記憶化的其他功能包括 unmemoize
、unmemoize_all
和 memoize_all
,可開啟或關閉記憶化。
- 主要貢獻者:Josh Peek
- 更多資訊
9.2 each_with_object
each_with_object
方法提供 inject
的替代方法,使用從 Ruby 1.9 向後移植的方法。它會迭代一個集合,將目前元素和 memo 傳遞到區塊中。
%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_email
和 vendor#account_password
。你也可以指定自訂前綴
class Vendor < ActiveRecord::Base
has_one :account
delegate :email, :password, :to => :account, :prefix => :owner
end
這將產生委派的方法 vendor#owner_email
和 vendor#owner_password
。
主要貢獻者:Daniel Schierbeck
9.4 其他 Active Support 變更
- 對
ActiveSupport::Multibyte
進行了廣泛的更新,包括 Ruby 1.9 相容性修復。 - 加入
ActiveSupport::Rescuable
,允許任何類別混合使用rescue_from
語法。 Date
和Time
類別的past?
、today?
和future?
,以方便日期/時間比較。Array#second
到Array#fifth
作為Array#[1]
到Array#[4]
的別名Enumerable#many?
封裝collection.size > 1
Inflector#parameterize
會產生輸入的 URL 就緒版本,用於to_param
中。Time#advance
可辨識小數天和週,因此你可以執行1.7.weeks.ago
、1.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 應用程式更加獨立,可以將 Rails 應用程式所需的所有 gem 複本放置在 /vendor/gems
中。此功能首先出現在 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 建立的 vendor gem 與 Rails 2.2 的儲存方式一致
你可以在命令列上指定 GEM=_gem_name_
來解壓縮或安裝單一 gem。
- 主要貢獻者:Matt Jones
- 更多資訊
10.2 其他 Railties 變更
- 如果你是 Thin Web 伺服器的愛好者,你會很高興知道
script/server
現在直接支援 Thin。 script/plugin install <plugin> -r <revision>
現在適用於基於 git 的外掛程式以及基於 svn 的外掛程式。script/console
現在支援--debugger
選項- 在 Rails 原始碼中包含設定持續整合伺服器以建置 Rails 本身的說明
rake notes:custom ANNOTATION=MYFLAG
允許你列出自訂註釋。- 將
Rails.env
包裝在StringInquirer
中,以便你可以執行Rails.env.development?
- 為了消除過時警告並正確處理 gem 相依性,Rails 現在需要 rubygems 1.3.1 或更高版本。
11 已棄用
此版本中棄用了一些舊程式碼
Rails::SecretKeyGenerator
已由ActiveSupport::SecureRandom
取代render_component
已棄用。如果你需要此功能,可以使用可用的 render_components 外掛程式。在渲染 partial 時,隱式局部變數指定已棄用。
def partial_with_implicit_local_assignment @customer = Customer.new("Marcel") render :partial => "customer" end
先前,上述程式碼會在 partial '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 核心的
Date
和Time
類別算術。Request#relative_url_root
已棄用。請改用ActionController::Base.relative_url_root
。
12 鳴謝
發行說明由 Mike Gunderloy 編譯