Rails 3.2を4.0にアップグレードする(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

Rails 3.2を4.0にアップグレードする(翻訳)

本記事はUpgrade Railsシリーズの1つです。シリーズの他の記事についてはこちらをクリックしてください

前回の記事では、マイグレーションを考慮する際の一般的なヒントについて触れましたので、本記事ではもう少し先に進みます。最初にRailsを3.2から4.0にアップグレードし、次に4.1、最終的に4.2にアップグレードします。所要時間はアプリの複雑さに応じて、開発者1人で1週間かかることもあれば、開発者2人で数か月かかることもあります。

  1. Rubyバージョン
  2. Gem
  3. Configファイル(config/)
  4. アプリケーションコード
    • a. モデル(app/models/)
    • b. コントローラ(app/controllers/)
  5. テスト
  6. その他
  7. 次のステップ

1. Rubyバージョン

Ruby 3.2.xは、Ruby 1.8.7をサポートする最後のバージョンです。アプリでRuby 1.8.7を使っている場合、Rubyを1.9.3以上にアップグレードする必要があります。本ガイドではRubyのアップグレードについて扱いませんので、詳しくはこちらのガイドをご覧ください。

2. Gem

rails4_upgradeというgemをRails 3プロジェクトのGemfileに追加して、アップデートの必要なgemを確認します。

$  myproject git:(develop) ✗ bundle exec rake rails4:check

** GEM COMPATIBILITY CHECK **
+------------------------------------------+----------------------------+
| Dependency Path                          | Rails Requirement          |
+------------------------------------------+----------------------------+
| devise 2.1.4                             | railties ~> 3.1            |
| devise-encryptable 0.2.0 -> devise 2.1.4 | railties ~> 3.1            |
| friendly_id 4.0.10.1                     | activerecord < 4.0, >= 3.0 |
| strong_parameters 0.2.3                  | actionpack ~> 3.0          |
| strong_parameters 0.2.3                  | activemodel ~> 3.0         |
| strong_parameters 0.2.3                  | activesupport ~> 3.0       |
| strong_parameters 0.2.3                  | railties ~> 3.0            |
+------------------------------------------+----------------------------+

現在バンドルされているgemやGemfile.lockを手動で調べなくても、アップグレードの必要なgemのレポートを生成できます。

3. Configファイル

Railsにはrails:updateというタスクが含まれています。これを、こちらの記事で説明されているガイドとして使うことができます。configファイルやinitializerから不要なコードやモンキーパッチを取り除くときに役立ちます。特に、Rails 2で動いていたRails 3アプリので有用です。

他の方法として、RailsDiffというサイトで基本的なRailsアプリの3.2から4.0への変更点をチェックすることもできます。このサイトでは他のバージョン間の変更点もチェックできます。

冒険してみたい方は、このスクリプトをお試しください。これは(RailsDiffで表示されているパッチと同じような感じで)Railsアプリにこのgitパッチ の適用を試行し、3.2から4.0に移行します。ただし複雑なアプリや成熟したアプリに適用するとコンフリクトが発生するためおすすめしません。

4. アプリケーションコード

a. モデル

  • .find_by_...を除くすべての動的finderメソッドが非推奨になります。
# 移行前
Authentication.find_all_by_provider_and_uid(provider, uid)

# 移行後
Authentication.where(provider: provider, uid: uid)

これらのfinderメソッドは、activerecord-deprecated_finders gemを追加することで使えるようになります。

  • ActiveRecordのスコープではlambdaが必要になりました。
# 移行前
default_scope where(deleted_at: nil)

# 移行後
default_scope { where(deleted_at: nil) }

# 移行前
has_many :posts, order: 'position'

# 移行後
has_many :posts, -> { order('position') }

(なお、default_scopeはくれぐれも慎重にお使いください)

  • 保護された属性は非推奨になりましたが、protected_attributes gemをインストールして引き続き使うことは可能です。ただし、RailsコアチームはRails 5.0からこのgemをサポート対象外にしているため、いずれにしろそのモデルはStrong Parametersに移行するべきですではありません

モデルを移行するには、attr_accessibleへの呼び出しをモデルから削除し、モデルに対応するコントローラにuser_paramsモデル名_paramsといった名前で新しいメソッドを追加する必要があります。

class UsersController < ApplicationController
  def user_params
    params.require(:user).permit(:name, :email)
  end
end

最後に、params[:user]への(ほとんどの)参照を、コントローラのアクション内のuser_paramsに変更します。この参照が更新や作成に使われる場合は(user.update_attributes(params[:user])など)、user.update_attributes(user_params)に変更します。この新しいメソッドは、Userモデルのname属性やemail属性の利用を許可し、Userモデルのその他の属性(idなど)への書き込みをすべて禁止します。

  • ActiveRecord ObserversはRails 4.0のコードベースから削除され、gemに切り出されました。Gemfileに以下を追加することで使えるようになります。
gem 'rails-observers' # https://github.com/rails/rails-observers

別の方法として、wisper gemか、もう少し違うアプローチとしてRailsのconcern(Rails4.0以降で追加)をチェックしてみてもよいでしょう。

  • ActiveResourceは削除され、独自のgemに切り出されました。
gem 'active_resource' # https://github.com/rails/activeresource

b. コントローラ

  • ActionController Sweeperはrails-observers gemに切り出されました。Gemファイルに以下を追加することで使えるようになります。
gem 'rails-observers' # https://github.com/rails/rails-observers

  • Action cachingは独自のgemに切り出されました。この機能をもう一度使いたい場合は、以下のいずれかの方法を使います。
caches_page   :public

または

caches_action :index, :show

その場合次のgemを追加する必要があります。

gem 'actionpack-action_caching' # https://github.com/rails/actionpack-action_caching

5. テスト

Ruby 1.9からはtest-unit gemをGemfileに追記する必要があります(標準ライブラリから削除されたため)。または、MinitestRSpecなど好みのテストフレームワークに移行します。

6. その他

  • ルーティングでリクエストメソッドの指定が必須になったため、デフォルトの「catch-all」動作に依存できなくなりました。
# これは以下のいずれかに変更する
match '/home' => 'home#index'

# こちら
match '/home' => 'home#index', via: :get

# またはこちら
get '/home' => 'home#index'
  • Rails 4.0からはプラグインのサポートが廃止されたため、プラグインをgemに置き換える必要があります。RubyGemsGithubでgemを探すか、プラグインをlibディレクトリに移動してRailsアプリで必要な箇所でrequireします。

7. 次のステップ

以上の手順が無事終了すれば、Rails 4.0を実行できるはずです。

アプリを微調整したい場合は、ぜひFastRuby.ioであなたのアップグレード結果をお気軽にお知らせください。

関連記事

Railsのdefault_scopeは使うな、絶対(翻訳)

Ruby on RailsによるWEBシステム開発、Android/iPhoneアプリ開発、電子書籍配信のことならお任せください この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833

コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。
これまでにRuby on Rails チュートリアル第2版の半分ほど、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れてそれぞれ一部を翻訳。
かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。
実は最近Go言語が好き。
仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

BPSアドベントカレンダー

週刊Railsウォッチ

インフラ

BigBinary記事より

ActiveSupport探訪シリーズ