RailsにMySQLを導入したことで、text型カラムのデフォルト値を設定できなくなった話

Rails

先日、自分の開発しているプロダクトにDockerを導入し、DBにMySQLを用いるように設定しました。すると、マイグレートする際にエラーが発生してしまいました。

MySQLを導入する前までは、問題なくマイグレートできていたので原因はなんなのかと悩みました。調べていくとMySQLでは、text型のカラムにデフォルト値を設定することができない、ということがわかった。

何とかしてデフォルト値を設定する方法はないかと調べた結果、解決することができたのでその過程を残しておこうと思います。

キーワード:MySQL、Model、Migration

エラー内容

Rails7のアプリケーションにDockerを導入し、データベースにMySQLを用いることにしました。すると、text型のカラムにはデフォルト値が設定できない、というエラーが発生してしまい、その解決法がわかりませんでした。

Mysql2::Error: BLOB, TEXT, GEOMETRY or JSON column 'カラム名' can't have a default value

解決法

デフォルト値が代入されていることを前提にアプリケーションを開発してしまったため、今頃になってデフォルト値がなくても大丈夫なように修正することはとても面倒。なので、空のモデルが生成されたときに、モデル内のメソッドを用いてデフォルト値を代入してくれるようにしました。

after_initialize :set_default_values, if: :new_record?
def set_default_values
    self.impression ||= ""
end

set_default_valuesメソッドを定義しました。デフォルト値を設定したいカラムが空(nil)の場合に、任意のデフォルト値(今回は空文字)を代入するという処理をしています。

ちなみに||=という演算子は、「左オペランドがnilまたはfalseの場合に右オペランドの値を代入する」という意味です。(今回の解決法を調べていく中で知りました。)

また、新しくオブジェクトが生成された後すぐにデフォルト値を設定して欲しいので、after_initializeを用いました。しかし、after_initializeはデータベースからレコードが読み込まれた時にも動作してしまうため、これを防がなくてはいけませんでした。

そのために、if: :new_record?という新しく作られたレコードの場合のみ、という条件を加えてあります。

まとめ

この記事のまとめ

今回のエラーを通して、||=演算子とafter_initializeについて知りました。

after_initializeがレコードを参照する場合でも動作してしまうことが、つまずきポイントになりそうだと感じました。

コメント

タイトルとURLをコピーしました