Engineering

Mar 01, 2018

Rails5.1すでに存在するカラムをmigrationでnot nullにする

change_column_nullを使う

すでに存在するカラムをマイグレーションでnullにするには、change_column_nullを使います。

class ChangeLikeCountToPost < ActiveRecord::Migration[5.1]
  def change
    change_column_null :posts, :like_count, null: false, 0
  end
end

change_column_nullはDBの定義をnull:オプションで指定した定義に変更するまえに、値がnullのものを第4引数にupdateしたのちにDB定義を変更してくれます。

def change_column_null(table_name, column_name, null, default = nil) #:nodoc:
  unless null || default.nil?
    execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
  end

  change_column table_name, column_name, nil, null: null
end

change_columnでもDBの定義は変更できますが、このメソッドは問答無用でDBの定義を変更しにいくので、「値がNullのカラムにNotNull制約をつけることはできません」となって怒られます。

 change_column_nullはDBのデフォルト値も変更してくれるわけではない

下のコードをみると、NotNull制約をつけるついでにDBのデフォルト値も設定してくれそうに見えますが、

change_column_null :posts, :like_count, null: false, 0

実際は、そこまでやってくれません。第四引数の0はnullの値を置き換える値を指定するだけでデフォルト値を指定しているわけではないことに注意しなければいけません。

そのため、NotNull制約をつけるついでにデフォルト値も設定する場合は、以下のようにする必要があります。

class ChangeLikeCountToPost < ActiveRecord::Migration[5.1]
  def change
    change_column_null :posts, :like_count, null: false, 0
    change_column :posts, :like_count, :integer, default: 0
  end
end

関連記事

記事検索

気になるサイト内の記事を検索する

プロフィール

バンクーバー在住のフルスタックエンジニアです。React, Ruby on Rails, Go などでお仕事しています。職場がトロントなので日本、トロント、バンクーバーの三つの時天空を操って生活しています。

プロモーション