彼女からは、おいちゃんと呼ばれています

ウェブ技術や日々考えたことなどを綴っていきます

Rails 4 へ移行してあらためて大切だと思ったこと + 役に立ったリンクを全力まとめ

先週 babyshark を Rails 3.2.13 から Rails 4.0.0 にアップデートしました。巷の情報では

StrongParameters さえ気をつけておけば、なんとかなる <<

的な。いやいや、たしかに Rails 2.3 -> 3.0 ほどの大変さではないにしろ、結構大変でしたよ。嘗めてかかるとエライ目に遭うと思います。

というわけで、移行してみて改めて大切だと思ったことと、ハマったポイントを共有します。久しぶりの長文。全力でいきますよ。

**Rails 4 へ移行してあらためて大切だと思ったこと + 役に立ったリンクを全力まとめ -1. Rails 3.2 との変更点を把握しておく -2. 使っている gem が Rails 4 に対応しているか確認する -3. 事前に Rails 3.2 の最新バージョンまで上げておく -4. gem もできるだけ最新バージョンにしておく -5. テストを書いておく -6. 移行を手助けしてくれる gem を把握しておく -7. 移行するか新しくつくり直すか検討する -8. 設定ファイルの差分を把握しておく -9. ハマりどころまとめ --(1) バリデータの正規表現 --(2) Sweeper が使えなくなった --(3) jQuery の live が効かなくなった --(4) rake test:prepare できない --(5) Capybara さんがぁあああ --(6) Bootstrap のデザインが崩れた --(7) Capistrano からデプロイできない --(8) その他 -10. DEPRECATION WARNING の駆逐 --(1) 名前付きスコープを lambda 記法にする --(2) will_paginate の order 指定 -参考書籍 <<

*1. Rails 3.2 との変更点を把握しておく

これはもう、当たり前ですけども。把握しないでバージョン上げちゃうのは自殺行為です。

細かい点を含めると結構変更点があるので、どんな変更点があるのか事前に把握しておくの必須です。WEB+DB PRESS vol.73 に「詳解 Rails4」という特集が載っているので、それに目を通すのがきっと一番良い方法です。

WEB+DB PRESS Vol.73

WEB+DB PRESS Vol.73

どうしてもウェブ情報が良い(だって無料だし)という人は、下記リンクあたりかなー

-Rails 4 パート1:Rails 4の最新情報 (翻訳版) | Engine Yard Blog JP -Rails 4 パート2:Rails 4の最新情報 | Engine Yard Blog JP -#400 What's New in Rails 4 - RailsCasts -» Rails4 社内勉強会レポート TECHSCORE BLOG

いやー、でもやっぱり、WEB+DB PRESS のほうを推したいなー。36ページにもわたって、詳しく分かりやすく書かれていますので。

*2. 使っている gem が Rails 4 に対応しているか確認する

大事。Rails 4 に上げた後に動かないことに気づいたら、進むも地獄、戻るも地獄です。。

それ専用のサイトがあったのですが、まだまだ情報が出揃っていない感じがありますね。。

-Ready for Rails 4?

人柱さんに感謝しましょう。

-» Rails4 ライブラリ対応状況調査 TECHSCORE BLOG

ちなみに babyshark では、検索機能にお手軽な MetaSearch(meta_search)を使っていたのですが、現時点で Rails 4 に対応しておらず、かつ開発も止まっているようなので、後継らしい Ransack に乗り換えました。

-ernie/meta_search -ernie/ransack

*3. 事前に Rails 3.2 の最新バージョンまで上げておく

いま現在 Rails 3.2 の最新バージョンが 3.2.14。できるだけ最新のバージョンから移行させた方が無駄にハマらなくて済むと思います。

*4. gem もできるだけ最新バージョンにしておく

あと、後述しますが、今回 僕がハマったのは、Rails 4 そのものよりも移行に伴う、周辺 gem のアップデートに起因する点が多いです。使っている gem も、移行前にできるだけ最新のものにしておいた方が良いでしょう。

特に Capybara は、バージョン上げたらテストこけるとか結構あるので、事前に上げて潰しておいた方が(ゼッタイに)良いです。

-jnicklas/capybara

*5. テストを書いておく

テストを書かなくても許されるのは(ry

事前にいろいろ準備しておいても、Rails 4 に上げた直後は、テストが盛大にこけます。が、それはテストを書いていればこそ気づける修正箇所なので、テストはきちんと書いておきましょう。ね。

*6. 移行を手助けしてくれる gem を把握しておく

移行を手助けしてくれる gem を大別すると、次の 2つがあります。

-(1) Rails 4 の機能を Rails 3.2 でも使えるようにするもの -(2) Rails 4 で本体から切り捨てられた機能を Rails 4 でも使えるようにするもの

(1) のタイプとしては、例えば Rails 3.2 で StrongParameters を使えるようにする strong_parameters とか。

-rails/strong_parameters

(2) のタイプとしては、Rails 4 で attr_accessible を使えるようにする protected_attributes とか。同じく Rails 4 で sweeper(opserver)を使えるようにする rails-observers とか。他にもキャッシュ関係、セッション、いろいろ。

-rails/protected_attributes -rails/rails-observers

下記が詳しいです。

-#415 Upgrading to Rails 4 - RailsCasts

Rails 4 の変更点を把握した上で、上記の gem との付き合い方を決めておく。

個人的には、移行をできるだけスムーズに行うために、積極的に (1) のタイプの gem を利用するのが賢明かなと思います。あと、いずれ書き換えるつもりでかつ移行前に書き換え可能なものは、移行前に書き換えてしまう。

また、後述しますが、移行直後、まずは最短で動くようにして、テストを通したかったので、(2) のタイプの gem にもお世話になりました。

*7. 移行するか新しくつくり直すか検討する

みんな大好き「Rails チュートリアル」には、Rails 3.2 からの「移行」ではなくて、Rails 4 でアプリケーションを「新規につくって、そこに Rails 3.2 のファイルを移していく」方法が推奨されています。

一見回り道に感じますが、アプリケーションの規模が小さいときは、こちらのやり方のほうが近道かもしれません。

-Ruby on Rails チュートリアル:実例を使って Rails を学ぼう

ちなみに僕の場合は、移行、つまり rake rails:update する方法を選びました。どちらのやり方のほうが早かったのかは微妙なところですが、新規にアプリケーションをつくるとなると Git のログが激しいことになりそうだったので避けたという感じです。

*8. 設定ファイルの差分を把握しておく

上記 7. のうち、「新規作成」ではなく「移行」する方法をとる場合には、バージョン間の設定ファイルの差分を把握しておくと何かと捗ります。

-RailsDiff

他のプロジェクトのプルリクエスト差分も参考になりました。

-Upgrading to Rails 4 · capistrano/capistrano Wiki

*9. ハマりどころまとめ

さて、移行に伴うハマりどころについて、先人のありがたい情報をまとめます。リンクが見つからないものは自前で書きます。

**(1) バリデータの正規表現

Rails 4 からバリデータの正規表現が厳しくなりました。複数行の文字列に対して ^ とか $ を使っていたらエラーが出ます。詳細は下記リンク参照。

The provided regular expression is using multiline anchors (^ or $), which may present a security risk. Did you mean to use \A and \z, or forgot to add the :multiline => true option? <<

-Rails4では正規表現が厳しくなった。 - Transparency of SE

**(2) Sweeper が使えなくなった

Sweeper を利用してキャッシュの削除を行っていましたが、エラーが出ました。

undefined method `cache_sweeper' for VideosController:Class <<

まだ継続して使いたいので、rails-observers を入れました。

**(3) jQuery の live が効かなくなった

Rails 4 へのアップデートとともに、jQuery のバージョンも上がるので、例えば live とか、動かなくなるメソッドを書き換える必要があります。 -jQuery 1.9 に更新する際に注意すべき変更点の自分なりのまとめ | 私的なjQuery

**(4) rake test:prepare できない

Rails 3.2 のときは rake db:test:prepare ってしてましたが、Rails 4 からは rake test:prepare というコマンドになりました(前のコマンドも使える)。が、下記のエラーでこけました。

cannot load such file -- zip/zip <<

rubyzip の 0.9.9 を入れて解決。1.0.0 だとダメでした。

-activerecord - Error in HEROKU app/vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:251:in - Stack Overflow

|ruby| gem 'rubyzip', '0.9.9' ||<

**(5) Capybara さんがぁあああ

今回の移行により capybara のバージョンを上げました(1.1.4 -> 2.1.0)。そうしたら、テストがこけるこける。。Rails になくてはならない神 gem のひとつですが、バージョンアップのたびに泣かされる人続出ですね。。

そういえば、過去に一度 2.0 に上げようとして、これ無理ゲーだわと思って戻したのを思い出しました。2.1 になって、いろいろとオプションで挙動を変えられるようになったようです。

-Introducing Capybara 2.1 ― Elabs

英語が無理ゲーな人は下記参照。内容はだいたい同じっす。

-Capybaraが2.1.0になって、また微妙に挙動が変わったので調べてみた - joker1007の日記 -capybara 2.1 を学ぶ - willnet.in

書き方の変更とか。

|diff| - it { expect(subject).to have_selector('title', text: "AV女優一覧 - #{I18n.t('site_name')}") } + it { expect(subject).to have_title("AV女優一覧 - #{I18n.t('site_name')}") } ||<

オプションの変更。下記は meta タグのテストのために書いたものです。

|diff| + Capybara.ignore_hidden_elements = false ||<

**(6) Bootstrap のデザインが崩れた

おそらく Rails 4 関係ないですけど。移行に伴い Bootstrap 関係のバージョンが上がって、一部のデザインが崩れました。何が言いたいかというと、場合によっては、移行作業にデザイナのサポートも必要だということです。

|diff| - bootstrap-sass (2.0.4.0) + bootstrap-sass (2.3.2.0) - bootstrap-will_paginate (0.0.6) + bootstrap-will_paginate (0.0.9) - bootswatch-rails (0.0.12) + bootswatch-rails (0.5.0) ||<

**(7) Capistrano からデプロイできない

移行に伴い Capistrano 2.15.5 に上げてデプロイしようとしたら、こけました。

僕の場合は、正常に動いていた 2.15.0 までバージョンを下げて対処しましたが、公式に対処方法が書かれていました。manifest.yml を手動でコピーしてあげるとか。

-Upgrading to Rails 4 · capistrano/capistrano Wiki -rails3からrails4に移行してcap deployするとasset:precompileが失敗する - kanetann's blog

**(8) その他

再掲になりますが、やはりこのあたりの必ず目を通しておいた方が良いかも。定番ぽい。

-#415 Upgrading to Rails 4 - RailsCasts -Ruby on Rails チュートリアル:実例を使って Rails を学ぼう

devise, friendly_id, acts_as_paranoid -> paranoia, format バリデータの正規表現ほか。今回僕は遭遇しませんでしたが、ログイン周りでこけたら恐怖ですね。

-CurryBu を Rails 4 にアップデートしてハマったところ | 暇人じゃない

multi_db 等 MySQL まわり。このあたりもハマりたくないなー。

-iQON Rails4.0への移行に関して① ~MySQLのgemを修正~ | VASILY TECH BLOG

*10. DEPRECATION WARNING の駆逐

まあ、急いでやる必要はないのかもしれませんが、気持ちとして、早くスッキリしたいですしね。。

**(1) 名前付きスコープを lambda 記法にする

EPRECATION WARNING: Using #scope without passing a callable object is deprecated. For example scope :red, where(color: 'red') should be changed to scope :red, -> { where(color: 'red') }. There are numerous gotchas in the former usage and it makes the implementation more complicated and buggy. (If you prefer, you can just define a class method named self.red.). (called from ... <<

下記のような感じで書き換えます。

|diff| - scope :available, where(status: Settings.tag.status.available) + scope :available, -> { where(status: Settings.video.status.available) } ||<

**(2) will_paginate の order 指定

DEPRECATION WARNING: #apply_finder_options is deprecated. <<

will_paginate の order 指定は、paginate メソッドの外に出します。

|diff| @videos = Video.available. - paginate(page: params[:page], - order: order_text(params[:order]), - per_page: per_page). + order(order_text(params[:order])). + paginate( + page: params[:page], + per_page: per_page) ||<

以上です。最後までお付き合いいただきありがとうございました。みなさまにおかれましては、無事に移行できますように!

*参考書籍

いろいろ書いたけど、やっぱり Rails 4 の良いところを正しく使うには、下記は必読だと思います。

WEB+DB PRESS Vol.73

WEB+DB PRESS Vol.73