1 升級至 Rails 3.1
如果您要升級現有的應用程式,最好先做好完善的測試涵蓋。您也應該先升級到 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 供應商化 Gems
Rails 現在在應用程式根目錄中使用 Gemfile
來判斷您的應用程式啟動所需的 gem。這個 Gemfile
由 Bundler gem 處理,然後安裝所有相依性。它甚至可以將所有相依性在本機安裝到您的應用程式,使其不依賴於系統 gem。
更多資訊:- 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 提供支援,並在資產管道指南中涵蓋。
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
gem 提供。應用程式產生器接受一個選項
-j
,它可以是任意字串。如果傳遞「foo」,則會將 gem「foo-rails」新增至Gemfile
,並且應用程式 JavaScript 資訊清單需要「foo」和「foo_ujs」。目前只有「prototype-rails」和「jquery-rails」存在,並透過資產管道提供這些檔案。除非指定
--skip-gemfile
或--skip-bundle
,否則產生應用程式或外掛程式會執行bundle install
。控制器和資源產生器現在會自動產生資產存根(可以使用
--skip-assets
關閉)。如果這些函式庫可用,這些存根將使用 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
。預設情況下,ActionController::Base
中會執行helper :all
,這會預設包含所有 helpers。將include_all_helpers
設定為false
將會只包含 application_helper 以及對應於 controller 的 helper(例如 foo_controller 的 foo_helper)。url_for
和具名的 URL helpers 現在接受: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
來忽略 accept headers。將
Rack::Cache
加入了預設的堆疊。將 etag 的責任從
ActionDispatch::Response
移到了 middleware 堆疊。依賴
Rack::Session
stores API 以獲得在 Ruby 世界中更高的相容性。這是不相容的回溯變更,因為Rack::Session
期望#get_session
接受四個參數,並且需要#destroy_session
而不是簡單的#destroy
。樣板查詢現在會進一步向上搜尋繼承鏈。
5.3 Action View
為
form_tag
新增了一個:authenticity_token
選項,以進行自訂處理或通過傳遞:authenticity_token => false
來省略 token。建立了
ActionView::Renderer
,並為ActionView::Context
指定了一個 API。Rails 3.1 中禁止就地
SafeBuffer
變異。新增了 HTML5
button_tag
helper。file_field
會自動將:multipart => true
加入到封閉的表單中。新增了一個方便的慣用語,可以從選項的
:data
雜湊中在 tag helpers 中產生 HTML5 data-* 屬性。tag("div", :data => {:name => 'Stephen', :city_state => %w(Chicago IL)}) # => <div data-name="Stephen" data-city-state="["Chicago","IL"]" />
鍵會變成 dasherized。值會被 JSON 編碼,除了字串和符號。
csrf_meta_tag
已重新命名為csrf_meta_tags
,並為了向後相容性而將csrf_meta_tag
設定為別名。舊的樣板處理器 API 已被棄用,新的 API 僅要求樣板處理器回應呼叫。
rhtml 和 rxml 最終從樣板處理器中移除。
config.action_view.cache_template_loading
已被帶回,允許決定是否應快取樣板。提交表單 helper 不再產生 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 gem 使用 JavaScriptHelper 在樣板中新增的Object#j()
方法。允許在日期時間選擇器中使用 AM/PM 格式。
auto_link
已從 Rails 中移除,並提取到 rails_autolink gem 中
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 Fixtures 已被棄用,並且在 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 body 已刷新後清理連接池。在 Active Record 上新增了一個
update_column
方法。這個新方法會更新物件上的指定屬性,跳過驗證和回呼。建議使用update_attributes
或update_attribute
,除非您確定您不想執行任何回呼,包括修改updated_at
欄位。它不應在新紀錄上呼叫。具有
:through
選項的關聯現在可以使用任何關聯作為 through 或 source 關聯,包括其他具有: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
。此外,只有當 source 反射是 belongs_to 時,這才能起作用。對於其他情況,您應直接修改 through 關聯。has_and_belongs_to_many
和has_many :through
的association.destroy
行為已變更。從現在開始,關聯上的 'destroy' 或 'delete' 將被視為表示「擺脫連結」,而不是(必然)「擺脫相關的紀錄」。先前,
has_and_belongs_to_many.destroy(*records)
會銷毀紀錄本身。它不會刪除連接表格中的任何紀錄。現在,它會刪除連接表格中的紀錄。先前,
has_many_through.destroy(*records)
會銷毀紀錄本身,以及連接表格中的紀錄。[注意:情況並非總是如此;先前版本的 Rails 只會刪除紀錄本身。] 現在,它只會銷毀連接表格中的紀錄。請注意,此變更在某種程度上是不相容的回溯變更,但很遺憾,在變更之前沒有辦法「棄用」它。進行此變更是為了使不同類型的關聯之間「銷毀」或「刪除」的意義保持一致。如果您希望銷毀紀錄本身,則可以執行
records.association.each(&:destroy)
。將
:bulk => true
選項新增到change_table
,以使用單一 ALTER 語句來變更在區塊中定義的所有 schema 變更。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 中定義了無法反轉的內容,則在向下遷移時將會引發IrreversibleMigration
異常。遷移現在使用實例方法,而不是類別方法
class FooMigration < ActiveRecord::Migration def up # Not self.up # ... end end
從模型和建構式遷移產生器(例如,add_name_to_users)產生的遷移檔案,會使用可逆遷移的
change
方法,而不是普通的up
和down
方法。移除了在關聯上插值字串 SQL 條件的支援。相反,應使用 proc。
has_many :things, :conditions => 'foo = #{bar}' # before has_many :things, :conditions => proc { "foo = #{bar}" } # after
在 proc 內部,
self
是關聯的所有者物件,除非您正在急切載入關聯,在這種情況下,self
是關聯所在的類別。您可以在 proc 內加入任何「正常」條件,因此以下內容也將起作用
has_many :things, :conditions => proc { ["foo = ?", bar] }
先前
has_and_belongs_to_many
關聯上的:insert_sql
和:delete_sql
允許您呼叫 'record' 來取得正在插入或刪除的記錄。現在會將其作為參數傳遞給 proc。新增了
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
將會複製記錄,包括呼叫 after initialize 勾點。凍結狀態不會被複製,並且所有關聯都會被清除。一個被複製的記錄將會針對new_record?
返回true
,擁有一個nil
的 id 欄位,且可儲存。查詢快取現在可與預處理語句一起使用。應用程式不需要任何變更。
7 Active Model
attr_accessible
接受一個選項:as
來指定角色。InclusionValidator
、ExclusionValidator
和FormatValidator
現在接受一個選項,它可以是 proc、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?
的別名反向移植。在 Date/DateTime/Time 中新增
weeks_ago
和prev_week
。為
ActiveSupport::Dependencies.remove_unloadable_constants!
新增before_remove_const
回呼。
棄用
ActiveSupport::SecureRandom
已被棄用,建議使用 Ruby 標準函式庫中的SecureRandom
。
10 致謝
請參閱 Rails 的完整貢獻者列表,了解眾多花費大量時間使 Rails 成為穩定且強大的框架的人們。向他們所有人致敬。
Rails 3.1 版本說明由 Vijay Dev 編寫。