加载中
A new Rails version is about to be released and it’s coming with many changes, deprecations, and new features.


Let’s take a look at what you need to do to get your app ready for Rails 4.

一个新的 Rails 版本即将发布了,随之带来了很多的修改、依赖和新特性。

让我们看一下,要使用 Rails 4,你需要为你的应用准备些什么。

The Path to Upgrade

The easiest way to be ready for Rails 4 is having your app on Rails 3.2.
If you are not in 3.2, upgrading should be done by minor versions. That is from 3.0 to 3.1, and then from 3.1 to 3.2.

升级的方式

要为 Rails 4 做好准备最简单的方法就是让你的应用运行在 Rails 3.2 上。如果你目前还不是使用 Rails 3.2,建议使用小版本方式升级,就是说从 3.0 升级到 3.1 ,然后再从 3.1 升级到 3.2

Deprecations

Some things are going to be completely removed on Rails 4. We should know about them and be prepared for the upgrade.

Ruby 1.9.3+ Only

Rails 4 is going to target only Ruby 1.9.3 and future versions. So make sure that your app runs on it.

If you’re using Ruby 1.9.x, the upgrade should be pretty straightforward.

If you’re still on Ruby 1.8.7, things could be a bit more work.

废弃 Deprecations

一些方法将在 Rails 4 中被完全删除,我们应该知道这些,并事先做好准备。

Rails 4 只支持 Ruby 1.9.3+

Rails 4 将只支持 Ruby 1.9.3 或者更新的版本,因此必须确保你的应用可在 Ruby 1.9.3 版本上运行。

如果你使用的是 Ruby 1.9.x,这样升级会更加直接。

如果你还在使用 Ruby 1.8.7,那需要做多点工作。

Nowadays most gems should be running on 1.9 or have a replacement.
Tools like rvm or rbenv help a lot by letting you run multiple versions of Ruby.

Using conditional statements in your Gemfile come in handy for having different gems on each environment until you get it all running on 1.9.

现在大多数 gems 都可以运行在 Ruby 1.9 版本,或者也有了替代品。例如 rvmrbenv 这样的工具可以帮助我们的应用程序运行在多个 Ruby 的版本。

在你的 Gemfil 中使用条件语句可以方便的处理不同环境下的不同 gems,直到你完全移植到 Ruby 1.9.x 上。

It should look something like this:

gem 'ruby18-only-gem', :platforms => :ruby_18
gem 'ruby19-only-gem', :platforms => :ruby_19
#More on this can be seen in the Bundler manpages:
#http://gembundler.com/man/gemfile.5.html#PLATFORMS-platforms-

A great resource for 1.8 vs 1.9 changes is the Ruby 1.9 walkthrough by Peter Cooper. Strongly recommended!

例如:

gem 'ruby18-only-gem', :platforms => :ruby_18
gem 'ruby19-only-gem', :platforms => :ruby_19
#More on this can be seen in the Bundler manpages:
#http://gembundler.com/man/gemfile.5.html#PLATFORMS-platforms-

关于 1.8 和 1.9 之间的改变可看 Peter Cooper 写的这篇文章 the Ruby 1.9 walkthrough . 强烈推荐!

No More vendor/plugins

Rails 4 will be removing Rails::Plugins class. Therefore, any code in the vendor/plugins directory won’t be loaded.

Most apps were already relying on gems instead of vendored plugins. However, if you still have any code in vendor/plugins, you have 2 options:

  • Move it to a gem. Most plugins should already have a gem version. If not, you can reference it from your Gemfile via the:gitor:pathoptions.
  • Move it tolib/your\_pluginand require it from an initializer onconfig/initializers.

Here’s the commit where this was deprecated.

不再有 vendor/plugins

Rails 4 将删除 Rails::Plugins 类,所以将不会再加载 vender/plugins 目录下的任何代码。

大多数应用应该依赖于 gems 而不是插件。但如果你在 vender/plugins 中还有一些代码,你有两种选择:

  • 改用 gem 方式实现,多数插件已经有了 gem 版本,如果没有你可以在 Gemfile 中通过 :gitor:pathoptions 来引用插件
  • 移到 lib/your\_pluginand ,然后在 onconfig/initializers 初始化

这里是关于废弃插件的说明 commit

Route Matching

On routes, thematchmethod will no longer act as a catch-all option. You should now specify which HTTP verb to respond to with the option:via

#Rails 3.2
match "/users/:id" => "users#show"
#Rails 4.0
match "/users/:id" => "users#show", via: :get
#or specify multiple verbs
match "/users" => "users#index", via: [:get, :post]

Another option for better Rails 3.2 compatibility is to just specify your actions with explicitget,post, or any other HTTP verb. With this option, you still get your code running today and future proof it for the upgrade.

#Rails 3.2 and 4.0 compatible
get "/users/:id" => "users#show"
# multiple verbs
get "/users" => "users#index"
post "/users" => "users#index"

路由匹配

关于路由,匹配方法不再作为是 catch-all 选项,你可以指定需要响应什么 HTTP 方法,包括 GET/POST 之类的。

#Rails 3.2
match "/users/:id" => "users#show"
#Rails 4.0
match "/users/:id" => "users#show", via: :get
#or specify multiple verbs
match "/users" => "users#index", via: [:get, :post]

另外一个更好兼容 Rails 3.2 的方法是显式的指定 HTTP 方法,是 GET 或者 POST,或者是其他的方法。这样你就可以兼容现在的版本和 Rails 4.0.

#Rails 3.2 and 4.0 compatible
get "/users/:id" => "users#show"
# multiple verbs
get "/users" => "users#index"
post "/users" => "users#index"

ActiveRecord Scopes Need A Callable object

In Rails 4, all ActiveRecord scopes must be defined with a callable object (likeProcorlambda):

#Rails 3.2
scope :recent, where(created_at: Time.now - 2.weeks)
#Rails 4
scope :recent, -> { where("created_at > ?", Time.now - 2.weeks).order("created_at desc") }
scope :active, -> { where(status: 'active') }

This helps avoid subtle bugs with Date or Time objects that get evaluated once, instead of being dynamically evaluated.

ActiveRecord

ActiveRecord 范围需要一个 Callable 对象。

在 Rails 4 中,所有 ActiveRecord 范围必须使用一个 callable 对象来定义:

#Rails 3.2
scope :recent, where(created_at: Time.now - 2.weeks)
#Rails 4
scope :recent, -> { where("created_at > ?", Time.now - 2.weeks).order("created_at desc") }
scope :active, -> { where(status: 'active') }

这个可避免一些关于日期和时间对象的微小 bug,无需动态的评估。

Removed Code

A lot of code was also removed from Rails 4 codebase. Don’t worry, though, most is still alive as separate gems. This helps upgraders with smooth transiitons.

Removed code:

被移除的代码

在 Rails 4 中有很多代码会被删除,别担心,因为大多数被删除的代码还会作为独立的 gems 存在,这样有助于更平滑的迁移。

被删除的代码包括:


A special note for the latter is worth mentioning:

Activerecord-deprecated-finders will be a default dependency on Rails 4.0 to provide the deprecated functionality. But it will removed on 4.1. As such, you should pay close attention to all warnings and start fixing them!

Rails guides provides a helpful explanation on changing most common cases on dynamic finders:

All dynamic methods except for findby… and findby…! are deprecated. Here’s how you can rewrite the code:

  • find_all_by_...can be rewritten usingwhere(...).
  • find_last_by_...can be rewritten usingwhere(...).last.
  • scoped_by_...can be rewritten usingwhere(...).
  • find_or_initialize_by_...can be rewritten usingwhere(...).first_or_initialize.
  • find_or_create_by_...can be rewritten usingfind_or_create_by(...)orwhere(...).first_or_create.
  • find_or_create_by_...!can be rewritten usingfind_or_create_by!(...)orwhere(...).first_or_create!.

All these gems will help having a smooth transition. I’d recommend that, for a full Rails 4 experience, just use them in development allowing the warning messages to help you get all your code up to the latest syntax.

特别值得一提的注意事项:

Activerecord-deprecated-finders 是 Rails 4.0 中默认提供废弃功能的依赖包,但它也将在 4.1 版本中被删除。因此你需要密切关注所有的警告信息,并开始修复这些警告。

Rails 指南 提供一个很有用的解释,关于在大多数情况下如何修改动态查找器:

所有动态的方法除了 findby… 和 findby…! 外都已废弃,你可以使用如下的替代方法:

  • find_all_by_...改为 where(...).
  • find_last_by_...改为 where(...).last.
  • scoped_by_...改为 where(...).
  • find_or_initialize_by_...改为 where(...).first_or_initialize.
  • find_or_create_by_...改为 find_or_create_by(...) 或者 where(...).first_or_create.
  • find_or_create_by_...!改为 find_or_create_by!(...) 或者 where(...).first_or_create!.

所有的那些 gems 都可以帮你实现平滑的迁移。我的建议是:对一个完全的 Rails 4 环境,通过警告信息来帮你的代码适应于最新版本的语法。

返回顶部
顶部