先日、自分の開発しているプロダクトに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
がレコードを参照する場合でも動作してしまうことが、つまずきポイントになりそうだと感じました。
コメント