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
来确定应用程序启动所需的 gems。Gemfile
由 Bundler gem 处理,然后安装所有依赖项。它甚至可以将所有依赖项本地安装到您的应用程序中,这样它就不依赖于系统 gems。
更多信息:- 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
gems 提供。应用程序生成器接受一个选项
-j
,它可以是任意字符串。如果传递“foo”,则 gem“foo-rails”将添加到Gemfile
中,并且应用程序 JavaScript 清单文件将要求“foo”和“foo_ujs”。目前,只有“prototype-rails”和“jquery-rails”存在并通过资产管道提供这些文件。生成应用程序或插件会运行
bundle install
,除非指定了--skip-gemfile
或--skip-bundle
。控制器和资源生成器现在会自动生成资产存根(可以通过
--skip-assets
关闭)。这些存根将使用 CoffeeScript 和 Sass,如果这些库可用。脚手架和应用程序生成器在 Ruby 1.9 上运行时使用 Ruby 1.9 风格的哈希。要生成旧风格的哈希,可以传递
--old-style-hash
。脚手架控制器生成器为 JSON 创建格式块,而不是 XML。
Active Record 日志记录被定向到 STDOUT 并在控制台中内联显示。
添加了
config.force_ssl
配置,它会加载Rack::SSL
中间件并强制所有请求都使用 HTTPS 协议。添加了
rails plugin new
命令,它会生成一个包含 gemspec、测试和用于测试的模拟应用程序的 Rails 插件。在默认中间件栈中添加了
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
中完成的,这默认情况下包含所有助手。将include_all_helpers
设置为false
将导致只包含application_helper和与控制器相对应的助手(如 foo_controller 的 foo_helper)。url_for
和命名 URL 助手现在接受: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
为
form_tag
添加了一个:authenticity_token
选项,用于自定义处理或通过传递: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()
的别名。这取代了Object#j()
方法,该方法是 JSON gem 在使用 JavaScriptHelper 的模板中添加的。允许在日期时间选择器中使用 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 主体刷新后清理连接池。在 Active Record 上添加了一个
update_column
方法。此新方法更新对象上的给定属性,跳过验证和回调。建议使用update_attributes
或update_attribute
,除非你确定不想执行任何回调,包括修改updated_at
列。它不应在新的记录上调用。具有
: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
选项。出于历史和实际原因,尽管默认策略是:nullify
用于常规 has_many,但:delete_all
是association.delete(*records)
采用的默认删除策略。另外,这只有在源反射是 belongs_to 的情况下才有效。对于其他情况,你应该直接修改通过关联。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 只会销毁记录本身。]现在,它只销毁连接表中的记录。请注意,这种变化在一定程度上与以前不兼容,但不幸的是,在更改之前没有办法“弃用”它。进行此更改是为了使“destroy”或“delete”的含义在不同类型的关联中保持一致。如果你希望销毁记录本身,你可以执行
records.association.each(&:destroy)
。向
change_table
添加:bulk => true
选项,以便使用单个 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 中定义了无法反转的内容,则在向下执行时将引发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
将复制记录,包括调用初始化后的钩子。不会复制冻结状态,并且所有关联都将被清除。复制的记录将对new_record?
返回true
,具有nil
的 id 字段,并且可以保存。查询缓存现在可以使用准备好的语句。应用程序不需要进行任何更改。
7 Active Model
attr_accessible
接受一个选项:as
以指定角色。InclusionValidator
、ExclusionValidator
和FormatValidator
现在接受一个选项,该选项可以是 proc、lambda 或任何响应call
的对象。此选项将使用当前记录作为参数调用,并返回一个响应include?
的对象(用于InclusionValidator
和ExclusionValidator
),并为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 编译