LoginSignup
0
0

More than 1 year has passed since last update.

本番稼働中のRailsアプリでダウンタイムを発生させずにカラム名を変更したい

Posted at

本番稼働中のRailsアプリで、カラム名を変更したいという状況が最近ありました。
単純に rename_column :models, :before_column, :after_column とやろうと思いましたが、こうするとダウンタイムが発生してしまうことが分かりました。
そこでいろいろ調査して、実際に自分がダウンタイムを発生させずにカラム名を変更できた方法を書き残したいと思います。
この他にもやり方はいくつもありそうですが、1つの例として参考にしていただけますと幸いです。

環境

  • Ruby 3.0.1
  • Rails 6.0.4

手順

  1. カラム追加とデータ移行
  2. 既存ロジックの修正とignored_columns指定
  3. カラム削除

カラム追加とデータ移行

カラム追加

リネーム後のカラムを追加します。

add_column :models, :after_column, :boolean

データ移行

before_columnafter_column のデータ移行を行います。
自分は直接SQLを叩いて対応しました。

UPDATE models SET after_column = before_column;

既存ロジックの修正とignored_columns指定

既存ロジックの修正

before_column を参照している箇所を修正します。
after_column を参照するように修正します。

APIの破壊的な変更ではない場合

- if before_column
+ if after_column
    # 処理
  end

APIの破壊的な変更の場合

フロントやアプリが参照している場合は注意が必要です。
ざっくり以下の手順が必要になると思います。

  1. バックエンド側で、既存APIのロジック修正と新規APIの追加
  2. フロントエンド側で、既存APIから新規APIに参照先を変更
  3. バックエンド側で、既存APIの削除

以下にGraphQLを使っている場合の例を示します。

バックエンド側で、既存APIのロジック修正と新規APIの追加
app/graphql/types/model.rb
  field before_column, Boolean, 'リネーム前のカラム'
+ field after_column, Boolean, 'リネーム後のカラム'
+ def before_column
+   after_column
+ end
フロントエンド側で、既存APIから新規APIに参照先を変更
query.graphql
  query ModelQuery($id: Int!) {
    model(id: $id) {
-     beforeColumn
+     afterColumn
    }
  }
バックエンド側で、既存APIの削除
app/graphql/types/model.rb
- field before_column, Boolean, 'リネーム前のカラム'
  field after_column, Boolean, 'リネーム後のカラム'
- def before_column
-   after_column
- end

ignored_columns指定

以下の記述を該当モデルに追加します。
これにより、Railsからリネーム前のカラムが見えないようにします。

self.ignored_columns = %i[before_column]

カラム削除

リネーム前のカラムを削除します。

remove_column :models, :before_column

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0