更多内容请访问 rubyonrails.org:

Ruby on Rails 3.2 版本说明

Rails 3.2 中的亮点

  • 更快的开发模式
  • 新的路由引擎
  • 自动查询解释
  • 带标签的日志记录

这些版本说明仅涵盖主要更改。要了解各种错误修复和更改,请参阅变更日志或查看 提交列表 在 GitHub 上的 Rails 主要仓库中。

1 升级到 Rails 3.2

如果您要升级现有应用程序,建议您在进行升级之前拥有良好的测试覆盖率。您还应该先升级到 Rails 3.1(如果您尚未升级),并确保您的应用程序在尝试升级到 Rails 3.2 之前按预期运行。然后请注意以下更改

1.1 Rails 3.2 至少需要 Ruby 1.8.7

Rails 3.2 需要 Ruby 1.8.7 或更高版本。对所有先前 Ruby 版本的支持已正式停止,您应该尽快升级。Rails 3.2 也与 Ruby 1.9.2 兼容。

请注意,Ruby 1.8.7 p248 和 p249 存在导致 Rails 崩溃的序列化错误。自 1.8.7-2010.02 版本发布以来,Ruby Enterprise Edition 已修复了这些错误。在 1.9 方面,Ruby 1.9.1 不可使用,因为它会直接导致段错误,因此如果您想使用 1.9.x,请升级到 1.9.2 或 1.9.3 以确保顺利运行。

1.2 在您的应用程序中需要更新的内容

  • 更新您的 Gemfile 以依赖于

    • rails = 3.2.0
    • sass-rails ~> 3.2.3
    • coffee-rails ~> 3.2.1
    • uglifier >= 1.0.3
  • Rails 3.2 弃用了 vendor/plugins,Rails 4.0 将完全删除它们。您可以开始通过将这些插件提取为 gem 并将它们添加到您的 Gemfile 中来替换它们。如果您选择不将它们制作成 gem,您可以将它们移动到例如 lib/my_plugin/* 中,并在 config/initializers/my_plugin.rb 中添加一个适当的初始化器。

  • 您可能需要在 config/environments/development.rb 中添加一些新的配置更改

    # Raise exception on mass assignment protection for Active Record models
    config.active_record.mass_assignment_sanitizer = :strict
    
    # Log the query plan for queries taking more than this (works
    # with SQLite, MySQL, and PostgreSQL)
    config.active_record.auto_explain_threshold_in_seconds = 0.5
    

    mass_assignment_sanitizer 配置也需要添加到 config/environments/test.rb

    # Raise exception on mass assignment protection for Active Record models
    config.active_record.mass_assignment_sanitizer = :strict
    

1.3 在您的引擎中需要更新的内容

用以下内容替换 script/rails 中注释下的代码

ENGINE_ROOT = File.expand_path('../..', __FILE__)
ENGINE_PATH = File.expand_path('../../lib/your_engine_name/engine', __FILE__)

require "rails/all"
require "rails/engine/commands"

2 创建 Rails 3.2 应用程序

# You should have the 'rails' RubyGem installed
$ rails new myapp
$ cd myapp

2.1 将 Gem 归档

Rails 现在在应用程序根目录中使用 Gemfile 来确定应用程序启动所需的 gem。此 GemfileBundler gem 处理,然后安装所有依赖项。它甚至可以将所有依赖项本地安装到您的应用程序中,以便它不依赖于系统 gem。

更多信息:Bundler 主页

2.2 走在前沿

BundlerGemfile 使冻结您的 Rails 应用程序变得像做饼一样容易,只需使用新的专用 bundle 命令即可。如果您想直接从 Git 仓库进行捆绑,可以传递 --edge 标志

$ rails new myapp --edge

如果您有 Rails 仓库的本地签出,并且想使用它来生成应用程序,可以传递 --dev 标志

$ ruby /path/to/rails/railties/bin/rails new myapp --dev

3 主要功能

3.1 更快的开发模式和路由

Rails 3.2 带有一个明显更快的开发模式。受 Active Reload 的启发,Rails 仅在文件实际更改时才重新加载类。在大型应用程序上,性能提升非常显著。由于使用了新的 Journey 引擎,路由识别速度也大大提高了。

3.2 自动查询解释

Rails 3.2 带有一个很好的功能,它通过在 ActiveRecord::Relation 中定义 explain 方法来解释 Arel 生成的查询。例如,您可以运行类似 puts Person.active.limit(5).explain 的代码,然后 Arel 生成的查询就会被解释。这允许您检查正确的索引和进一步的优化。

在开发模式下,运行时间超过半秒的查询会自动被解释。当然,此阈值可以更改。

3.3 带标签的日志记录

在运行多用户、多帐户应用程序时,能够按操作者对日志进行筛选非常有用。Active Support 中的 TaggedLogging 通过用子域、请求 ID 以及任何其他有助于调试此类应用程序的信息来标记日志行,从而帮助您做到这一点。

4 文档

从 Rails 3.2 开始,Rails 指南可用于 Kindle 和 iPad、iPhone、Mac、Android 等的免费 Kindle 阅读应用程序。

5 Railties

  • 通过仅在依赖项文件发生更改时才重新加载类来加快开发速度。可以通过将 config.reload_classes_only_on_change 设置为 false 来关闭此功能。

  • 新的应用程序在环境配置文件中获得一个标志 config.active_record.auto_explain_threshold_in_seconds。在 development.rb 中的值为 0.5,在 production.rb 中被注释掉。在 test.rb 中没有提到。

  • 添加了 config.exceptions_app 来设置在发生异常时由 ShowException 中间件调用的异常应用程序。默认值为 ActionDispatch::PublicExceptions.new(Rails.public_path)

  • 添加了一个 DebugExceptions 中间件,其中包含从 ShowExceptions 中间件中提取的功能。

  • rake routes 中显示已挂载引擎的路由。

  • 允许使用 config.railties_order(如下所示)更改 railties 的加载顺序

    config.railties_order = [Blog::Engine, :main_app, :all]
    
  • 对于没有内容的 API 请求,脚手架返回 204 无内容。这使得脚手架能够与 jQuery 开箱即用。

  • 更新 Rails::Rack::Logger 中间件以将 config.log_tags 中设置的任何标签应用于 ActiveSupport::TaggedLogging。这使得用调试信息(如子域和请求 ID)标记日志行变得容易 - 这些信息对调试多用户生产应用程序非常有帮助。

  • 可以在 ~/.railsrc 中设置 rails new 的默认选项。您可以在主目录中的 .railsrc 配置文件中指定每次运行 rails new 时要使用的额外命令行参数。

  • destroy 添加了一个别名 d。这也适用于引擎。

  • 脚手架和模型生成器上的属性默认设置为字符串。这允许以下操作:bin/rails g scaffold Post title body:text author

  • 允许脚手架/模型/迁移生成器接受“index”和“uniq”修饰符。例如,

    $ bin/rails g scaffold Post title:string:index author:uniq price:decimal{7,2}
    

    将为 titleauthor 创建索引,其中后者是唯一索引。某些类型(如 decimal)接受自定义选项。在示例中,price 将是一个精度和比例分别设置为 7 和 2 的 decimal 列。

  • 从默认 Gemfile 中删除了 turn gem。

  • 删除了旧的插件生成器 rails generate plugin,转而使用 rails plugin new 命令。

  • 移除旧的 config.paths.app.controller API,转而使用 config.paths["app/controller"]

5.1 已弃用功能

  • Rails::Plugin 已弃用,将在 Rails 4.0 中移除。请使用 gems 或 bundler 添加带有路径或 git 依赖项的插件,而不是将插件添加到 vendor/plugins 中。

6 Action Mailer

  • mail 版本升级到 2.4.0。

  • 移除旧的 Action Mailer API,该 API 自 Rails 3.0 起已弃用。

7 Action Pack

7.1 Action Controller

  • ActiveSupport::Benchmarkable 设为 ActionController::Base 的默认模块,以便 #benchmark 方法再次在控制器上下文中可用,就像以前一样。

  • caches_page 添加了 :gzip 选项。默认选项可以使用 page_cache_compression 在全局配置中设置。

  • 现在,当使用 :only:except 条件指定布局,而这些条件不满足时,Rails 将使用您的默认布局(例如 "layouts/application")。

    class CarsController
      layout 'single_car', :only => :show
    end
    

    当请求进入 :show 操作时,Rails 将使用 layouts/single_car,当请求进入任何其他操作时,Rails 将使用 layouts/application(如果存在,则使用 layouts/cars)。

  • form_for 更改为使用 #{action}_#{as} 作为 CSS 类和 ID(如果提供了 :as 选项)。早期版本使用 #{as}_#{action}

  • Active Record 模型上的 ActionController::ParamsWrapper 现在仅在设置了 attr_accessible 属性时才会包装它们。如果没有,则只会包装类方法 attribute_names 返回的属性。这通过将嵌套属性添加到 attr_accessible 中来修复嵌套属性的包装。

  • 每次 before 回调停止时,记录 "Filter chain halted as CALLBACKNAME rendered or redirected"。

  • ActionDispatch::ShowExceptions 已重构。控制器负责选择是否显示异常。可以在控制器中覆盖 show_detailed_exceptions? 来指定哪些请求应在错误时提供调试信息。

  • 响应器现在针对没有响应正文的 API 请求返回 204 No Content(如新的脚手架)。

  • ActionController::TestCase 的 cookies 已重构。现在,为测试用例分配 cookie 应使用 cookies[]

    cookies[:email] = '[email protected]'
    get :index
    assert_equal '[email protected]', cookies[:email]
    

    要清除 cookie,请使用 clear

    cookies.clear
    get :index
    assert_nil cookies[:email]
    

    我们现在不再写出 HTTP_COOKIE,并且 cookie 容器在请求之间是持久的,因此如果您需要为测试操作环境,则需要在创建 cookie 容器之前进行。

  • 如果未提供 :typesend_file 现在会从文件扩展名中猜测 MIME 类型。

  • 已添加 PDF、ZIP 和其他格式的 MIME 类型条目。

  • 允许 fresh_when/stale? 使用记录而不是选项哈希。

  • 将缺少 CSRF 令牌的警告日志级别从 :debug 更改为 :warn

  • 资产应默认使用请求协议,或者如果不可用则默认使用相对路径。

7.1.1 已弃用功能

  • 已弃用对父级具有显式布局设置的控制器的隐式布局查找

    class ApplicationController
      layout "application"
    end
    
    class PostsController < ApplicationController
    end
    

    在上面的示例中,PostsController 将不再自动查找 posts 布局。如果您需要此功能,可以从 ApplicationController 中删除 layout "application",或者在 PostsController 中明确将其设置为 nil

  • 已弃用 ActionController::UnknownAction,转而使用 AbstractController::ActionNotFound

  • 已弃用 ActionController::DoubleRenderError,转而使用 AbstractController::DoubleRenderError

  • 已弃用 method_missing,转而使用 action_missing 来处理缺少的操作。

  • 已弃用 ActionController#rescue_actionActionController#initialize_template_classActionController#assign_shortcuts

7.2 Action Dispatch

  • 添加 config.action_dispatch.default_charset 来配置 ActionDispatch::Response 的默认字符集。

  • 添加了 ActionDispatch::RequestId 中间件,它将使响应中可使用唯一的 X-Request-Id 标头,并启用 ActionDispatch::Request#uuid 方法。这使得在堆栈中端到端跟踪请求以及在混合日志(如 Syslog)中标识单个请求变得容易。

  • ShowExceptions 中间件现在接受一个异常应用程序,该应用程序负责在应用程序失败时呈现异常。应用程序使用 env["action_dispatch.exception"] 中的异常副本以及重写为状态码的 PATH_INFO 调用。

  • 允许通过 railtie 配置救援响应,如 config.action_dispatch.rescue_responses

7.2.1 已弃用功能

  • 已弃用在控制器级别设置默认字符集的功能,请改用新的 config.action_dispatch.default_charset

7.3 Action View

  • ActionView::Helpers::FormBuilder 添加 button_tag 支持。此支持模拟 submit_tag 的默认行为。

    <%= form_for @post do |f| %>
      <%= f.button %>
    <% end %>
    
  • 日期帮助器接受一个新选项 :use_two_digit_numbers => true,它在不更改相应值的情况下,使用前导零呈现月份和日期的选择框。例如,这对于显示 ISO 8601 风格的日期(如 '2011-08-01')很有用。

  • 您可以为表单提供一个命名空间,以确保表单元素上的 ID 属性的唯一性。命名空间属性将在生成的 HTML ID 上添加下划线作为前缀。

    <%= form_for(@offer, :namespace => 'namespace') do |f| %>
      <%= f.label :version, 'Version' %>:
      <%= f.text_field :version %>
    <% end %>
    
  • select_year 的选项数量限制为 1000。传递 :max_years_allowed 选项以设置自己的限制。

  • content_tag_fordiv_for 现在可以接受记录的集合。如果您在块中设置接收参数,它也会将记录作为第一个参数传递。因此,您不必这样做

    @items.each do |item|
      content_tag_for(:li, item) do
        Title: <%= item.title %>
      end
    end
    

    您可以这样做

    content_tag_for(:li, @items) do |item|
      Title: <%= item.title %>
    end
    
  • 添加了 font_path 帮助器方法,该方法计算 public/fonts 中字体资产的路径。

7.3.1 已弃用功能

  • 将格式或处理程序传递给 render :template 及其类似方法(如 render :template => "foo.html.erb")已弃用。相反,您可以直接将 :handlers:formats 作为选项提供:render :template => "foo", :formats => [:html, :js], :handlers => :erb

7.4 Sprockets

  • 添加了配置选项 config.assets.logger 来控制 Sprockets 日志记录。将其设置为 false 以关闭日志记录,设置为 nil 以默认为 Rails.logger

8 Active Record

  • 布尔值列使用 "on" 和 "ON" 值时会被类型转换为 true。

  • timestamps 方法创建 created_atupdated_at 列时,它默认情况下会将它们设置为不可为空。

  • 已实现 ActiveRecord::Relation#explain

  • 已实现 ActiveRecord::Base.silence_auto_explain,它允许用户选择性地在代码块内禁用自动 EXPLAIN。

  • 已实现对慢查询的自动 EXPLAIN 日志记录。新的配置参数 config.active_record.auto_explain_threshold_in_seconds 决定什么被认为是慢查询。将其设置为 nil 将禁用此功能。默认情况下,在开发模式下为 0.5,在测试和生产模式下为 nil。Rails 3.2 在 SQLite、MySQL(mysql2 适配器)和 PostgreSQL 中支持此功能。

  • 添加 ActiveRecord::Base.store 用于声明简单的单列键值存储。

    class User < ActiveRecord::Base
      store :settings, accessors: [ :color, :homepage ]
    end
    
    u = User.new(color: 'black', homepage: '37signals.com')
    u.color                          # Accessor stored attribute
    u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor
    
  • 添加了仅针对给定范围运行迁移的功能,这允许仅从一个引擎运行迁移(例如,仅撤消需要从引擎中移除的更改)。

    rake db:migrate SCOPE=blog
    
  • 从引擎复制的迁移现在使用引擎名称进行范围限定,例如 01_create_posts.blog.rb

  • 已实现 ActiveRecord::Relation#pluck 方法,该方法直接从底层表返回一列值的数组。这也适用于序列化属性。

    Client.where(:active => true).pluck(:id)
    # SELECT id from clients where active = 1
    
  • 生成的关联方法是在一个单独的模块中创建的,以允许覆盖和组合。对于名为 MyModel 的类,模块名为 MyModel::GeneratedFeatureMethods。它在 Active Model 中定义的 generated_attributes_methods 模块之后立即包含到模型类中,因此关联方法会覆盖同名属性方法。

  • 添加 ActiveRecord::Relation#uniq 用于生成唯一查询。

    Client.select('DISTINCT name')
    

    ... 可以写成

    Client.select(:name).uniq
    

    这也允许您在关系中撤消唯一性

    Client.select(:name).uniq.uniq(false)
    
  • 在 SQLite、MySQL 和 PostgreSQL 适配器中支持索引排序顺序。

  • 允许关联的 :class_name 选项除了字符串之外还可以接受符号。这样做是为了避免混淆新手,并且与其他选项(如 :foreign_key)已经允许使用符号或字符串保持一致。

    has_many :clients, :class_name => :Client # Note that the symbol need to be capitalized
    
  • 在开发模式下,db:drop 还会删除测试数据库,以便与 db:create 对称。

  • 不区分大小写的唯一性验证避免在列已经使用不区分大小写的排序规则时在 MySQL 中调用 LOWER。

  • 事务性夹具列出所有活动的数据库连接。您可以在不禁用事务性夹具的情况下测试不同连接上的模型。

  • 向 Active Record 添加 first_or_createfirst_or_create!first_or_initialize 方法。与旧的 find_or_create_by 动态方法相比,这是一种更好的方法,因为它更清楚地说明了哪些参数用于查找记录,哪些参数用于创建记录。

    User.where(:first_name => "Scarlett").first_or_create!(:last_name => "Johansson")
    
  • 向 Active Record 对象添加了 with_lock 方法,该方法会启动事务,锁定对象(悲观地),然后向代码块传递控制权。该方法接受一个(可选)参数,并将其传递给 lock!

    这使得能够编写以下代码

    class Order < ActiveRecord::Base
      def cancel!
        transaction do
          lock!
          # ... cancelling logic
        end
      end
    end
    

    class Order < ActiveRecord::Base
      def cancel!
        with_lock do
          # ... cancelling logic
        end
      end
    end
    

8.1 已弃用功能

  • 线程中自动关闭连接已弃用。例如,以下代码已弃用

    Thread.new { Post.find(1) }.join
    

    它应该更改为在线程结束时关闭数据库连接

    Thread.new {
      Post.find(1)
      Post.connection.close
    }.join
    

    只有在应用程序代码中生成线程的人才需要担心这种变化。

  • set_table_nameset_inheritance_columnset_sequence_nameset_primary_keyset_locking_column 方法已弃用。请改用赋值方法。例如,请使用 self.table_name= 而不是 set_table_name

    class Project < ActiveRecord::Base
      self.table_name = "project"
    end
    

    或者定义您自己的 self.table_name 方法

    class Post < ActiveRecord::Base
      def self.table_name
        "special_" + super
      end
    end
    
    Post.table_name # => "special_posts"
    

9 Active Model

  • 添加 ActiveModel::Errors#added? 来检查是否已添加特定错误。

  • 添加了使用 strict => true 定义严格验证的功能,当验证失败时始终引发异常。

  • 提供 mass_assignment_sanitizer 作为替换 sanitiser 行为的简单 API。也支持 :logger(默认)和 :strict sanitiser 行为。

9.1 已弃用功能

  • 已弃用 ActiveModel::AttributeMethods 中的 define_attr_method,因为这仅是为了支持 Active Record 中的 set_table_name 等方法而存在的,而这些方法本身也正在被弃用。

  • 已弃用 Model.model_name.partial_path,转而使用 model.to_partial_path

10 Active Resource

  • 重定向响应:303 See Other 和 307 Temporary Redirect 现在表现得像 301 Moved Permanently 和 302 Found 一样。

11 Active Support

  • 添加了 ActiveSupport:TaggedLogging,它可以包装任何标准的 Logger 类以提供标记功能。

    Logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
    
    Logger.tagged("BCX") { Logger.info "Stuff" }
    # Logs "[BCX] Stuff"
    
    Logger.tagged("BCX", "Jason") { Logger.info "Stuff" }
    # Logs "[BCX] [Jason] Stuff"
    
    Logger.tagged("BCX") { Logger.tagged("Jason") { Logger.info "Stuff" } }
    # Logs "[BCX] [Jason] Stuff"
    
  • DateTimeDateTime 中的 beginning_of_week 方法接受一个可选参数,表示假设一周开始的日期。

  • ActiveSupport::Notifications.subscribed 在代码块运行时提供对事件的订阅。

  • 定义了新的方法 Module#qualified_const_defined?Module#qualified_const_getModule#qualified_const_set,它们类似于标准 API 中的相应方法,但接受限定的常量名。

  • 添加了 #deconstantize,它补充了 #demodulize 的词形变化。这会删除限定常量名中的最右边部分。

  • 添加了safe_constantize,它可以将字符串常量化,但如果常量(或其部分)不存在,则返回nil 而不是引发异常。

  • 使用Array#extract_options!时,ActiveSupport::OrderedHash 现在被标记为可提取的。

  • 添加了Array#prepend 作为Array#unshift 的别名,以及Array#append 作为Array#<< 的别名。

  • Ruby 1.9 中空白字符串的定义已扩展到 Unicode 空白字符。此外,在 Ruby 1.8 中,象形空间 U`3000 被视为空白字符。

  • 词形分析器理解缩写词。

  • 添加了Time#all_dayTime#all_weekTime#all_quarterTime#all_year 作为生成范围的一种方式。

    Event.where(:created_at => Time.now.all_week)
    Event.where(:created_at => Time.now.all_day)
    
  • instance_accessor: false 作为Class#cattr_accessor 及其朋友的一个选项添加。

  • ActiveSupport::OrderedHash 在使用接受其参数并使用展开运算符的块时,#each#each_pair 的行为现在有所不同。

  • 添加了ActiveSupport::Cache::NullStore 用于开发和测试。

  • 删除了ActiveSupport::SecureRandom,转而使用标准库中的SecureRandom

11.1 弃用

  • ActiveSupport::Base64 已被弃用,转而使用::Base64

  • 弃用了ActiveSupport::Memoizable,转而使用 Ruby 的记忆化模式。

  • Module#synchronize 已被弃用,没有替代方案。请使用 ruby 标准库中的监视器。

  • 弃用了ActiveSupport::MessageEncryptor#encryptActiveSupport::MessageEncryptor#decrypt

  • ActiveSupport::BufferedLogger#silence 已被弃用。如果您想在某个代码块中禁止日志,请更改该代码块的日志级别。

  • ActiveSupport::BufferedLogger#open_log 已被弃用。此方法本不应该公开。

  • ActiveSupport::BufferedLogger 自动为您的日志文件创建目录的行为已弃用。请确保在实例化之前创建日志文件的目录。

  • ActiveSupport::BufferedLogger#auto_flushing 已被弃用。您可以像这样设置底层文件句柄的同步级别。或者调整您的文件系统。现在,FS 缓存控制着刷新。

    f = File.open('foo.log', 'w')
    f.sync = true
    ActiveSupport::BufferedLogger.new f
    
  • ActiveSupport::BufferedLogger#flush 已被弃用。在文件句柄上设置同步,或者调整您的文件系统。

12 贡献者

查看Rails 的完整贡献者列表,了解为使 Rails 成为一个稳定而强大的框架而花费大量时间的人们。向他们所有人表示感谢。

Rails 3.2 版本说明由Vijay Dev 编写。



返回顶部