メインのAPIで利用しているRuby on Railsのバージョンを4.2から6.0に上げた話
こんにちは、エンジニアの鈴木です。最近のマイブームはサウナです。
今回はタイトルにもあるように、スペースマーケットのメインAPIで利用しているRuby on RailsというWebフレームワークのバージョンアップ対応についてご紹介します。
やったことの概要
今回は「Ruby on Railsのバージョンを4.2から6.0に」というメインのタスクがありましたが、合わせていくつかのサブタスクも行いました。
MultiDB対応
もともと複数DBへの接続を行うためにoctopusというgemを利用していましたが、Rails6から純正の機能でできるようになったので採用しました。
技術的負債だったsqliteを廃止
いくつかのモデルのマスターデータがsqliteで管理されており、運用が煩雑になってしまっていたため、これを機にmysqlにすべて移行するという対応を合わせて行いました。
古かったgemのバージョンアップ
Rails同様、上げたかったけれどなかなか対応できていなかったgemたちのバージョンを一緒に上げました。以下、いくつか抜粋します。
- devise
- doorkeeper
- geocoder
- stripe
Syntax的変更いろいろ
Railsを4系から一気に6系まで上げるため、多くのSyntax的な変更を行いました。こちらもいくつか抜粋します。
- model の uniqueness に case_sensitive 追加
- model の validate の if: に string を設定していた箇所を lambda に変更
- ActiveRecord の update_attributes を update に書き換え
- ActiveRecord::AttributeMethods::Dirtyのメソッド名変更対応
- rspec の requests の get/post 等のメソッドの params/headers の引数指定方法を変更
なぜやったのか
セキュリティリスクへの対応
Rails のメンテナンスポリシーは、新機能 (New feature)、バグ修正 (bug fixes)、セキュリティ問題 (security issues)、重大なセキュリティ問題 (severe security issue) の4つに分割されています。
上記の4つのうち、Rails4.2は「セキュリティ問題」と「重大なセキュリティ問題」のサポートが切れており、Rails自体にセキュリティ問題が発覚しても自力で修正する必要がある状態であり、そこから脱却するという目的がありました。
開発効率の向上
Railsのバージョンアップに伴い、新しく追加された機能や便利なメソッドなどが多数ありますので、それらが使えるようになることで開発効率の向上につながると考えました。
以下に、Rails5や6から使用できるようになった機能やメソッドを一部抜粋しました。
Rails5から使えるようになった機能、メソッド
- Enumerableモジュールに#pluck, #withoutが追加
- ActiveRecordの#saveにtouchオプションが追加
- ActiveRecord::Relation#in_batchesメソッドが追加
Rails6から使えるようになった機能、メソッド
- 並列テスト
- 複数DB接続
- DBへのバルクインサートの標準サポート
- ActiveRecord:Relation#pick
どうやったのか
ドキュメントの読み込み
まずは公式のドキュメントや他社の事例を読み込む、というところから始めました。
公式ドキュメントとしては、アップグレード方法がまとめられたアップグレードガイドと、リリース内容がまとめられたリリースノートがありますので、事前にこれらの資料を読み込み、対応内容や方針、影響範囲等の把握を行いました。
また、他社の似たような事例などもいくつか参考にしていました。
ローカル環境で動かしてみる
こちらは公式のガイドに基づいて対応し、特にハマらずに進めることができたと記憶しています。
ローカル環境でrails serverとrails consoleのコマンドが成功し、最低限アプリケーションが起動するところまでもっていきました。
落ちまくる単体テスト(Rspec)を通るようにする
この時点で500件ほどRspecの単体テストが落ちていました。
前半はSyntax的な一つの修正をほかのモデルやコントローラーに横展開するだけで数十件ずつ減らせたのですが、後半からは1件あたりの対応時間が増えていき、かなり焦っていたのを覚えています。
このとき大変だったのが、「テストコードを直すべきか、実装を直すべきか」の判断が難しかったということです。
かなり歴史があるAPIですので、概要すらも把握していない機能に遭遇し「仕様的に正しい挙動」や「そもそもこの機能は今も生きているのか?」などがわからず、調査に要する時間がかなりかかってしまいました。
最終的にテストをオールグリーンにするのに1ヶ月以上かかってしまいました。
単体テストでカバーできていない部分を打鍵テスト
sandbox環境で打鍵テストを行いました。
基本的な挙動は探偵テストで担保できていると考え、打鍵テストでは外部システムとの接続部分を重点的にテストしました。
また、バッチ処理や通知処理などの、Webサイトの表示部分以外の機能についてもこのタイミングでテストしました。
いざ、リリース
スペースマーケットのRailsのAPIは基本的にAWSのEC2インスタンス上で動作しており、capistranoによるデプロイを行っております。
今回のリリース対応時には、Rails6環境であらかじめ構築しておいたEC2インスタンスを新たに作成したターゲットグループ に紐付け、ALBレベルでのBlue/Greenデプロイを行いました。
まとめ
今回はスペースマーケットがメインAPIで利用しているRuby on Railsのバージョン対応についてご紹介しました。
目的としては「セキュリティリスクの低減」「開発効率の向上」があり、それらは無事達成できましたが、メジャーバージョンを2つあげるのはやはり大変でした。
Rails4系から6系に一気にあげたので、エラー原因のあたりが付けづらく、調査に要する時間が増加してしまいました。
今後は、バージョンアップ対応はできるだけ小さく計画的に行う必要があると感じました。
そのためにも「やらないことのリスク」を明確にした上で、高優先度のタスクとしてあらかじめ枠を確保してしまうといった対応を心がけようと思いました。
よかったこととして、事前のコード断捨離を行っておいたおかげで影響範囲を縮小でき、結果的に技術的負債を返しつつトータルの工数を減らせたことが挙げられます。
さいごに
スペースマーケットでは全方位的にエンジニアを募集中です。
ご興味を持たれた方は以下のリンクからどしどしご応募ください!
この記事が気に入ったらサポートをしてみませんか?