1 基礎架構
Rails 2.2 是 Rails 基礎架構的重大版本,讓 Rails 保持運作並連接至世界其他地區。
1.1 國際化
Rails 2.2 提供一個簡單的國際化系統(或 i18n,對於那些打字打到累的人來說)。
- 主要貢獻者:Rails i18 團隊
- 更多資訊
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
- 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 和 洪力來。
- 更多資訊
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 介面卡。
- 主要貢獻者:Adam Wiggins
- 更多資訊
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
- 主要貢獻者: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!
的新 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')
- 主要貢獻者:Josh Susser
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
以符合行為,讓關聯能正常運作。
- 主要貢獻者: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 會為七個預設動作(索引、顯示、建立、新增、編輯、更新和刪除)產生路由。但這些路由中的每個路由都會佔用應用程式的記憶體,並導致 Rails 產生額外的路由邏輯。現在,您可以使用 :only
和 :except
選項來微調 Rails 將為資源產生的路由。您可以提供單一動作、動作陣列或特殊的 :all
或 :none
選項。這些選項會由巢狀資源繼承。
map.resources :photos, :only => [:index, :show]
map.resources :products, :except => :destroy
- 主要貢獻者:Tom Stuart
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_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 現在提供對 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
記憶化的其他功能包括 unmemoize
、unmemoize_all
和 memoize_all
,用於開啟或關閉記憶化。
- 主要貢獻者:Josh Peek
- 更多資訊
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_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 應用程式更為獨立,可以在 /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 <plugin> -r <revision>
現在適用於基於 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 核心
Date
和Time
類別算術。Request#relative_url_root
已棄用。請改用ActionController::Base.relative_url_root
。
12 個學分
發行說明由 Mike Gunderloy 編譯
回饋
我們鼓勵您協助提升本指南的品質。
如果您發現任何錯字或事實錯誤,請協助我們修正。首先,您可以閱讀我們的 文件貢獻 部分。
您也可能會發現不完整的內容或未更新的內容。請務必為 main 新增任何遺漏的文件。請先查看 Edge Guides,以確認問題是否已在主分支中修復。請查看 Ruby on Rails 指南指南,了解風格和慣例。
如果您發現需要修復的地方,但無法自行修補,請 開啟問題。
最後,我們非常歡迎在 官方 Ruby on Rails 論壇 上針對 Ruby on Rails 文件進行任何討論。