1 升級到 Rails 3.1
如果你正在升級現有的應用程式,在開始之前,最好先有良好的測試涵蓋率。如果你還沒升級到 Rails 3,你應該先升級到 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 供應商寶石
Rails 現在會在應用程式根目錄中使用 Gemfile
來判斷應用程式啟動所需的寶石。這個 Gemfile
會由 Bundler 寶石處理,然後安裝所有相依性。它甚至可以將所有相依性安裝到應用程式的本機,讓它不依賴於系統寶石。
更多資訊:- bundler 主頁
2.2 處於邊緣
Bundler
和 Gemfile
讓您可以使用新的專用 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 提供支援,並在 Asset Pipeline 指南中進行說明。
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-rails
和prototype-rails
寶石提供。應用程式產生器接受一個選項
-j
,它可以是一個任意字串。如果傳遞「foo」,寶石「foo-rails」會新增到Gemfile
,而應用程式 JavaScript 清單需要「foo」和「foo_ujs」。目前只有「prototype-rails」和「jquery-rails」存在,並透過資產管線提供這些檔案。產生應用程式或外掛程式會執行
bundle install
,除非指定--skip-gemfile
或--skip-bundle
。控制器和資源產生器現在會自動產生資產 stub(這可以用
--skip-assets
關閉)。如果這些函式庫可用,這些 stub 會使用 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::Etag
和Rack::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
。預設情況下,helper :all
會在ActionController::Base
中執行,預設會包含所有 helper。將include_all_helpers
設定為false
將只會包含 application_helper 和對應於控制器的 helper(例如 foo_controller 的 foo_helper)。url_for
和命名 URL helper 現在接受: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
來忽略接受標頭。將
Rack::Cache
新增到預設堆疊。將 etag 責任從
ActionDispatch::Response
移到中間層堆疊。依賴
Rack::Session
儲存 API 以在 Ruby 世界中獲得更多相容性。這是向後不相容的,因為Rack::Session
預期#get_session
會接受四個引數,並需要#destroy_session
而非僅#destroy
。範本查詢現在會在繼承鏈中進一步搜尋。
5.3 Action View
新增
:authenticity_token
選項到form_tag
以進行自訂處理或透過傳遞:authenticity_token => false
來省略令牌。建立了
ActionView::Renderer
,並為ActionView::Context
指定了 API。Rails 3.1 中禁止了
SafeBuffer
就地變異。加入了 HTML5
button_tag
輔助工具。file_field
會自動將:multipart => true
加入到封閉的表單中。加入了一個方便的慣用語,用於從
:data
選項雜湊中,在標籤輔助工具中產生 HTML5 data-* 屬性tag("div", :data => {:name => 'Stephen', :city_state => %w(Chicago IL)}) # => <div data-name="Stephen" data-city-state="["Chicago","IL"]" />
鍵會以連字號分隔。值會以 JSON 編碼,字串和符號除外。
csrf_meta_tag
已重新命名為csrf_meta_tags
,並將csrf_meta_tag
別名化以維持向後相容性。舊的範本處理器 API 已過時,而新的 API 只需要範本處理器回應呼叫即可。
rhtml 和 rxml 已最終移除為範本處理器。
config.action_view.cache_template_loading
已帶回,它允許決定是否快取範本。提交表單輔助工具不再產生 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 寶石在使用 JavaScriptHelper 的範本中加入的Object#j()
方法。允許在日期時間選擇器中使用 AM/PM 格式。
auto_link
已從 Rails 中移除,並抽取到 rails_autolink 寶石
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 Fixture 已過時,且支援將在 Rails 3.2.0 中移除。
ActiveRecord#new
、ActiveRecord#create
和ActiveRecord#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 主體已快取後清除連線池。在 Active Record 上新增一個
update_column
方法。這個新方法會更新物件上的給定屬性,略過驗證和回呼。建議使用update_attributes
或update_attribute
,除非你確定不想要執行任何回呼,包括修改updated_at
欄位。不應在新的記錄上呼叫它。具有
:through
選項的關聯現在可以使用任何關聯作為 through 或來源關聯,包括其他具有: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_one
、belongs_to
)不再有代理,只會傳回關聯記錄或nil
。這表示你不應使用未記錄的方法,例如bob.mother.create
- 改用bob.create_mother
。支援
has_many :through
關聯上的:dependent
選項。由於歷史和實務原因,:delete_all
是association.delete(*records)
使用的預設刪除策略,儘管預設策略是常規has_many
的:nullify
。此外,只有在來源反映是belongs_to
時,這才有效。對於其他情況,你應直接修改 through 關聯。association.destroy
對has_and_belongs_to_many
和has_many :through
的行為已變更。從現在開始,關聯上的「destroy」或「delete」將被視為「擺脫連結」,而不是(不一定)「擺脫關聯記錄」。先前,
has_and_belongs_to_many.destroy(*records)
會銷毀記錄本身。它不會刪除關聯表格中的任何記錄。現在,它會刪除關聯表格中的記錄。先前,
has_many_through.destroy(*records)
會銷毀記錄本身和關聯表格中的記錄。[注意:這並非總是如此;先前版本的 Rails 只會刪除記錄本身。] 現在,它只會銷毀關聯表格中的記錄。請注意,此變更在某種程度上與過去不相容,但很不幸地,在變更之前無法「標示為過時」。此變更的目的是為了讓不同類型關聯的「銷毀」或「刪除」含義一致。如果您想要銷毀記錄本身,您可以執行
records.association.each(&:destroy)
。新增
:bulk => true
選項至change_table
,以使用單一 ALTER 陳述式來進行使用區塊定義的所有架構變更。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_one
和belongs_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
有些事情無法自動為您反轉。如果您知道如何反轉這些事情,您應該在您的遷移中定義
up
和down
。如果您在change
中定義了無法反轉的事情,在執行down
時會引發IrreversibleMigration
例外。遷移現在使用實例方法,而非類別方法
class FooMigration < ActiveRecord::Migration def up # Not self.up # ... end end
從模型和建構遷移產生器 (例如,add_name_to_users) 產生的遷移檔案使用可逆遷移的
change
方法,而非一般的up
和down
方法。已移除對關聯中內插字串 SQL 條件的支援。應改用程序。
has_many :things, :conditions => 'foo = #{bar}' # before has_many :things, :conditions => proc { "foo = #{bar}" } # after
在程序內,
self
是擁有關聯的物件,除非您正在急切載入關聯,這種情況下self
是關聯所在的類別。您可以在程序中擁有任何「正常」條件,因此以下內容也會運作
has_many :things, :conditions => proc { ["foo = ?", bar] }
先前,
has_and_belongs_to_many
關聯上的:insert_sql
和:delete_sql
讓您可以呼叫「記錄」來取得正在插入或刪除的記錄。這現在傳遞為程序的引數。新增
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_to
或references
欄位新增add_index
。設定
belongs_to
物件的 id 會更新對該物件的參考。ActiveRecord::Base#dup
和ActiveRecord::Base#clone
的語意已變更,以更接近一般的 Ruby dup 和 clone 語意。呼叫
ActiveRecord::Base#clone
會產生記錄的淺層拷貝,包括拷貝凍結狀態。不會呼叫任何回呼。呼叫
ActiveRecord::Base#dup
會複製記錄,包括呼叫初始化後掛勾。不會複製凍結狀態,且所有關聯都會清除。複製的記錄會傳回true
以表示new_record?
,具有nil
id 欄位,且可儲存。查詢快取現在可與準備好的陳述式搭配使用。應用程式不需要任何變更。
7 Active Model
attr_accessible
接受選項:as
來指定角色。InclusionValidator
、ExclusionValidator
和FormatValidator
現在接受選項,該選項可以是程序、lambda 或任何回應call
的內容。此選項會以目前的記錄作為引數呼叫,並傳回一個物件,該物件回應InclusionValidator
和ExclusionValidator
的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
,它會使STDOUT
和STDERR
靜音。新增
String#inquiry
作為一個方便的方法,用於將字串轉換為StringInquirer
物件。新增
Object#in?
來測試物件是否包含在另一個物件中。LocalCache
策略現在是一個真正的中間件類別,不再是匿名類別。已引入
ActiveSupport::Dependencies::ClassCache
類別,用於保存可重新載入類別的參考。已重新整理
ActiveSupport::Dependencies::Reference
,以直接利用新的ClassCache
。在 Ruby 1.8 中將
Range#cover?
作為Range#include?
的別名進行回溯。新增
weeks_ago
和prev_week
至 Date/DateTime/Time。新增
before_remove_const
回呼至ActiveSupport::Dependencies.remove_unloadable_constants!
。
不建議使用
- 不建議使用
ActiveSupport::SecureRandom
,建議改用 Ruby 標準函式庫中的SecureRandom
。
10 貢獻者
請參閱 Rails 貢獻者完整清單,了解許多人花費許多時間製作 Rails,使其成為穩定且強大的框架。向所有這些人致敬。
Rails 3.1 發行說明由 Vijay Dev 編輯
回饋
鼓勵您協助改善本指南的品質。
如果您發現任何錯字或事實錯誤,請協助我們修正。首先,您可以閱讀我們的文件貢獻章節。
您也可能會發現不完整或過時的內容。請協助新增任何遺漏的 main 文件。請務必先查看Edge Guides,以驗證問題是否已在主分支中修正。查看Ruby on Rails 指南準則,以了解風格和慣例。
如果您發現需要修正的內容,但無法自行修補,請開啟問題。
最後,歡迎在官方 Ruby on Rails 論壇上討論任何與 Ruby on Rails 文件相關的事項。