自社サービスのRails4を、Rails5にアップグレードした話

会社のRails4.2.0で動いているプロダクトは、Rails5.2.0へとアップグレードしたので、メモがてら大変だったことなどを書いておこうと思います。

何故やろうと思ったのか

Railsをアップグレードすることで便利な機能が追加されたと、得られる嬉しい事がいろいろあると思います。

ですが、弊社はエンジニアの人数が限られた組織ですので、下記の理由からなかなかRails5へのアップグレードに踏み切れませんでした。

  • Rails5にすることで、影響範囲がわからない
  • Railsに詳しいわけではないので、そもそもRails4からRails5へのやり方を調べる必要がある
  • エンジニアの人数が少ないので、優先度としては
  • 調査時間や実際に対応する時間を捻出するのが難しい

しかし、フレームワークのバージョンアップはこの先もずっとついて回る事ですし、ここでやらないと一生やらないと思ったからです。

また、実はこれから春に向けて当該サイトのリニューアルを予定してます。

リニューアルは主にフロントエンド周りとなるのですが、そこで個人としても今一番注目している「Nuxt.js」を利用したいと考えています。

「Nuxt.js」は今をときめく「Vue.js」のフレームワークでして、「Nuxt.js」を使い今よりもよりモダンなフロントエンド開発にすることで、開発効率の向上となによりUI/UXをより向上させることができるのではないかと考えております。

そういった予定もあり、Rails5化はその前にやってしまいたかったというお話でした。

何が一番大変だったのか

まず、何よりも一番問題になったのが、サイトを開発したエンジニアがすでに居ない事でした。

さらに開発ドキュメントも存在せず、「ある機能が実装された経緯」一つとってもワカラナイ状態です。

Rails5にバージョンアップ後、各機能が正常に動作するかを確認していくのですが、エラーとなる箇所全てにおいてロジックを書き換えることになります。

そうすると、”知っている人”に聞くことができないまま、エラーになるたびに「この機能の意図する所はこうだ」とロジックを全て追って理解するという作業が必要となり、これがとにかく大変でした。

実際にやった作業

余談ですが、Rails5にアップグレードするにあたって、基本的に下記のページを参考にしました。

Upgrading Ruby on Rails

Gemの依存関係

さて、実際にRails4からRails5にアップグレードする上で、実際やった作業です。

まず、Gemfileのrailsをアップデートします。

- gem 'rails', '4.2.0'
+ gem 'rails', '~> 5.2.0'

すると、 bundle install する際にGemの依存関係でエラーとなりので、ひとつづつ依存を解決していく必要があります。

この依存関係をひとつづつ解決する作業がかなり大変で、しかも私自身がRuby on Railsを始めて1年ほど人間だったので、恐らく無理だろうと判断しましました。

そして、少しディストピア感はあるのですが、代わりに下記の様に対応しました。

  • 開発向けのGemは一旦すべて削除
  • 現在Gemfileに設定されているGemを一つづつ「何をする・しているGemなのか」調べる
  • 本当に必要なGemだけ残し、それ以外は一旦削除する
  • 各々のGemのアップデートで起きた依存解決エラーを解決

これで、なんとかRailsを立ち上げるところまでできました。

各々のGemのアップデートで起きたエラーを修正

・何故か mysql2 のinstallが通らなくなった

原因は結局ワカラズでしたが、とりあえず xcode-select --installXCodeをインストールしたら mysql2 をインストールすることができました。(必要なパッケージが無かったっぽい?)

gem 'therubyracer'gem 'mini_racer' に変更

詳しくは下記。

https://github.com/rails/rails/pull/29285

xxx_filterxxx_action に修正

  • before_filterbefore_action に変更
  • around_filteraround_action に変更

コレですね

DEPRECATION WARNING: before_filter is deprecated and will be removed in Rails 5.1. Use before_action instead.

・ scope でチェインするような書き方を修正

where{ (category_id == target_category_id) }

のように書かれていた箇所を

where({category_id: target_category_id})

の様に修正しました。

これは単純にエラーを解消させた感じです。

・ 画像表示周りで、 .url が無く、エラーになる

こちらも単純にエラーを解消させた感じです。

また、ついでなのですが、下記の様にリンク付き画像を定義されている、

= link_to(image_tag(record.image, alt: record.alt.to_s), record.link, target: "_blank")

といった書き方をされていた箇所を

= link_to record.link, target: "_blank" do
  = image_tag record.image.url, alt: record.alt.to_s

といった様に修正しました。

リンクはリンク、画像は画像で、見通しがよくなった様に思います。

SQLエイリアス

例えば、

employees belongs_to companies というAssociationがあったとして

class Emoloyee < ActiveRecord::Base
  belongs_to :company
end

とすると思いますが、Rails5から belongs_to は必須項目になったので

class Emoloyee < ActiveRecord::Base
  belongs_to :company, optional: true
end

に修正しました。

FactoryGirl から FactoryBot への修正

恐らくこの作業が一番大切だと考えています。

まず、アプリケーションのテストが全く書かれていませんでした。

なので、とりあえずRSpecで重要ロジックのテストを書いておこうと思ったのですが、その上で、FactoryGirlが FactoryBot に名前が変更されたので、ついでにFactoryBotにしました。

まとめ

作業内容をまとめると、

  • 「Gemの依存関係解決」難易度:★★★★
  • 「ちょっとしたロジックの修正」難易度:★★
  • 「(とりあえず)足りない重要ロジックのテストを書く」難易度:★★

といった感じでした。

とりあえずこのくらいの作業でRails5へのアップグレードは完了し、稼働させることができました。

やってしまえばなんてことはありませんが、手探り状態で1週間ほど対応に時間がかかりました。

その間新規機能の開発などが止まることを考えると、経営目線では「Rails5へのアップグレードは本当に必要な作業なの?」と問われることも多々あるかもしれません。

長い目で見ると、いつか爆発するかもしれない爆弾とも言えそうな「Gemの依存解決」、フレームワークの新機能を使ったスピード感ある「開発効率の向上」などなど、必ず良い事だらけだと思います。