Rubyバージョンアップのやり方をまとめる

## はじめに

Railsアプリケーション内で使用するRubyバージョンアップの流れをまとめました。

というのも、「ruby バージョンアップ　やり方」で検索をかけたときにあまりまとまった記事を見つけられず、
「つまづくことがあまりないからヒットしないんだろうな・・・」と思いつつも不安になったので記事を書いてみました。

手順として抜けているとこが多々あるかとは思いますが、

どのように進めてよいかわからない方のすこしでも参考になればうれしく思います。

## もくじ

[1. はじめに](#はじめに)
[2. そもそものきっかけ](#そもそものきっかけ)
[3. バージョンアップのながれ](#バージョンアップのながれ)
[4. おわりに](#おわりに)
[5. 参考情報](#参考情報)

## そもそものきっかけ

Rubyのリリース情報をみている中で、担当プロジェクトのRubyバージョンをぼちぼちあげていかんのではないかと思い、
「よっしゃ、いっちょやってみっか！」っていうのがきっかけです。

個人開発でrailsのバージョンアップはしたことありましたが、当時は(今もですが)プログラミング経験が浅くそういえばRubyを更新した記憶がないので今後のためにもなると思った次第です。


## バージョンアップのながれ

ざっと今回の流れをまとめました。

大きくまとめると、動作確認 -> Ruby更新 -> 動作確認 (->その他)です。

なんでもそうだと思いますが、原因の切り分けができるステップになるよう意識しつつ行いました。

**バージョンアップ手順**
[1. 公式リリースのチェック](#1-公式リリースのチェック)
[2. 開発ブランチを作成する](#2-開発ブランチを作成する)
[3. RubyGemsのアップデート](#3-rubygemsのアップデート)
[4. 更新前チェック(Rspec)](#4-更新前チェックrspec)
[5. Rubyのインストール(rbenv)](#5-rubyのインストールrbenv)
[6. バージョン変更(.ruby-version)](#6-バージョン変更ruby-version)
[7. RubyGemsのアップデート](#7-rubygemsのアップデート)
[8. bundlerとgemのインストール](#8-bundlerとgemのインストール)
[9. 更新後チェック(Rspec)](#9-更新後チェックrspec)
[10. その他更新作業](#10-その他更新作業)

簡単ですが環境情報は以下の通りです(バージョン情報は伏せてます)。

```
OS: MacOS
MacOSパッケージ管理： homebrew
Rubyバージョン管理： rbenv
フレームワーク： Ruby on Rails
テストフレームワーク： Rspec
```

---

### 1. 公式リリースのチェック

まずはなんといっても[公式ページ](https://www.ruby-lang.org/ja/)のリリース情報チェックですね。

ポイントとしては、例えばパッチ(Ruby 2.7.2とか)のリリースノートだとマイナーアップデート(Ruby 2.7.0)の情報までは載ってません。
ですのでチェックするときは、アップデートしたいメジャー版リリースノート -> マイナー版リリースノート -> パッチ版リリースノートの順でみていくと良いと思います。

参考にRuby2.7.2の場合です。
[Ruby2.7のリリースノート](https://www.ruby-lang.org/ja/news/2019/12/25/ruby-2-7-0-released/)
[Ruby2.7.2のリリースノート](https://www.ruby-lang.org/ja/news/2020/10/02/ruby-2-7-2-released/)

変更箇所を全て把握することは難しくても、どのような変更点があったのかについて目を通しておくことは後々のバグ修正に役立つかもしれませんので習慣化しましょう(自分自身に言い聞かせる)。

### 2. 開発ブランチを作成する。

きちんと切り戻しが行えるようにRubyのバージョンアップ用ブランチで作業を行いましょう。
作業中に「うわー！！！やってしまったー！！！」ってときにも安心です。忘れずに。

```
# (例)2.7.2にバージョンアップする
# ブランチ名は参考です。

git checkout -b ruby-versionup-2.7.2
```

### 3. RubyGemsのアップデート

Rubyのバージョンが変わると、RubyGemsのバージョンも変更になりますのであらかじめ最新のものへアップデートしておきます([コメントいただきました](https://qiita.com/SHinGo-Koba/items/58dae3dbc4690aa35c24#comment-9fccf3b062987b515d62))。

Rubyバージョンアップ後にも最新版のRubyGemsにアップデートすることでバージョン差異をなくすことが目的です。

```
# RubyGemsを更新する。

gem update --system
```

### 4. 更新前チェック(Rspec)

Ruby更新の前に、テストを実施します。
Rspecと記載してますが、バージョンアップしたいプロジェクトで使用されているテストフレームワークで大丈夫です。

この過程のポイントは、Ruby更新前にあらかじめ問題なく動作することを保証しておくことです。

Rubyのバージョンアップが原因で動作しなくなったのか、それとも実はもともと存在していたバグなのかを切り分けられるように、必ず行いましょう。

```
# Rspecを動かす。

bundle exec rspec <rspecフォルダへのパスもしくはrspecファイルへのパス>
```

### 5. Rubyのインストール(rbenv)

当方Rubyのバージョン管理をrbenvで行ってます。ですのでrbenvでRubyをインストールします。
rbenvでのRubyインストールのやり方は[こちらの記事](https://qiita.com/_kanacan_/items/c1499f6c13b1c41da982)を参考に行いました。

```
# rbenvとrubyリストの更新
brew upgrade rbenv ruby-build

# リストの確認
rbenv install --list

# rubyのインストール。(例)Ruby2.7.2
rbenv install 2.7.2
```

### 6. バージョン変更(.ruby-version)

手順5でrbenv経由でRubyのインストールを行いました。
rbenvを利用しているときのRubyバージョン切り替えは①コマンドによる切り替え、②対象プロジェクトディレクトリ下の`.ruby-version`があります。

プロジェクトごとにバージョン管理したいこともあり、今回は`.ruby-version`によるRubyバージョンの切り替えを行います。

```
# プロジェクトのツリー図
hoge_pj/
 ├ app/
 ├ bin/
 ├ condig/
 ├ # その他いろいろ
 └ .ruby-version

# .ruby-version
# (例)Ruby2.7.2を指定する
2.7.2
```

念のため、Rubyがきちんと変更されているかをチェックします。
変更したRubyのバージョンが出力されればokです。

```
cd <対象プロジェクトのディレクトリ>
ruby --version 
```

### 7. RubyGemsのアップデート

Rubyが切り替わりましたので、手順3のときと同様にRubyGemsをアップデートし最新のもので統一します。

```
# RubyGemsを更新する。

gem update --system
```

### 8. bundlerとgemのインストール

次に、bundlerとgemをインストールします。

まずbundlerですが、Gemfile.lockで記載されているbundlerバージョンをインストールすることをおすすめします。

Ruby2.6以降であればbundlerが標準搭載されていますが、bundlerは `Gemfile.lockで記載されたbundlerバージョン > デフォルトbundlerバージョン`の順で実行されますので、Gemfile.lockで記載されているbundlerバージョンをインストールしておくとそのバージョンでの実行が可能です。

bundler更新の必要がある場合はRubyバージョンアップ作業が全て終わったあとに行い、なるべくRubyのバージョン以外は更新していない状況にすると何らかのエラーが発生した場合にも原因の切り分けが簡単です。

```
# Gemfile.lock
GEM
  remote: https://rubygems.org/
  specs:
    ... #いろいろなgemの情報
  
  ...
  ...

  BUNDLED WITH
    <bundlerのバージョン情報> # ここに記載されているバージョンでまずはインストール


# bundlerのインストール
gem install bundler -v <bundlerのバージョン>
```

続けて、プロジェクトで使用するgemをインストールします。
Gemfile.lockを基にインストールする場合は`bundle install` を実行します。

```
# gemのインストール
# --pathオプションは必要に応じて。

bundle install --path <指定したいインストール先のパス>
```

注意点として、この時点では`bundle update`によるgemインストールをしないことです。

`bundle update` ではGemfileに記載された内容で一からgem同士の依存関係を解決しgemのインストールを行います。
そのため、場合によってはgemライブラリのバージョンが元々使用していたものよりアップグレードしてしまうことがあり、Rubyのバージョン更新とは関わりのない箇所でエラーがでてしまう恐れがあります。

bundlerのときと同様に、gemのアップデートを行うのはRubyバージョンアップ作業が全て終わったあとにしましょう。

### 9. 更新後チェック(Rspec)

Rubyのバージョンアップが終わりましたので、手順4で行ったRspecを再度実行します。

バージョンアップ前にRspecが全てパスすることを確認しているため、テスト失敗箇所はほぼ間違いなくRubyの更新によるものだと考えてコード修正を行うことができます。

テストが落ちる箇所がある場合はエラー内容をみながらコード修正を行います。コード修正が終われば再度Rspecを実行し、全てのテストがパスするようにしましょう。


```
# 手順4と同じ
# Rspecを動かす。

bundle exec rspec <rspecフォルダへのパスもしくはrspecファイルへのパス>
```

### 10. その他更新作業

その他更新作業というのは、例えば、Dockerイメージを作成する際のベースイメージ更新などがあります。

```
# Dockerfile

FROM ruby:2.7.2-slim # 例えば、こういうところ。

RUN ...
...
```

Dockerイメージ更新の注意点でいうと、LinuxOSバージョンが変わる場合元々Dockerfile内で使われていたライブラリがインストールできなくなることがあります。
今回担当したプロジェクトだとopen-jdkをapt installしていたのですが、それがベースイメージの更新によってできなくなり修正をかけました。

なのでRubyのバージョン変更によってイメージビルド時にエラーがでないかチェックしましょう。
修正箇所や修正方法は記事の内容から脱線しますので、ここでは割愛します([そのときの対応はこちら](https://qiita.com/SHinGo-Koba/items/a73e5f345c22c5ebbf96))。

<br/>

Rspecが全てパスしその他更新作業がなければ、Rubyのバージョンアップは以上となります。

おつかれさまでした！

## おわりに

この記事ではRailsアプリケーション内で使用するRubyバージョンアップの流れをまとめました。

Rubyバージョンアップを終えてみて、思ってたよりすんなりいったなというのが率直な感想です(Dockerイメージ更新の際のLinuxライブラリ更新が一番時間かかった・・・)。
とはいえ、ある程度やり方の流れが決まっているとすごいストレスフリー(プラス 安心感)にできるなと感じました。

必要な手順あれば追加していきたいと思います。

## 参考情報

[Ruby公式](https://www.ruby-lang.org/ja/)
[rbenvでRubyのバージョンを最新安定版にupdate](https://qiita.com/_kanacan_/items/c1499f6c13b1c41da982)
[[初期設定]なぜ「.ruby-version」を作成するのか？](https://qiita.com/shimadama/items/74033b932800bb61b3f3)
[永久保存版！？伊藤さん式・Railsアプリのアップグレード手順](https://qiita.com/jnchito/items/0ee47108972a0e302caf)