すでに作成してあるテーブルのカラムに、あとからNULL制約をつける際に若干はまってしまったのでメモ。
migrationファイルを追加して、
db/migrate/20150210031823_change_status_of_diaries.rb
class ChangeStatusOfDiaries < ActiveRecord::Migration
def self.up
change_column_null :diaries, :status, false
end
def self.down
change_column_null :diaries, :status, true
end
end
実行すると、
% bundle exec rake db:migrate
== 20150210031823 ChangeStatusOfDiaries: migrating ========================
-- change_column_null(:experiences, :status, false)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::NotNullViolation: ERROR: column "status" contains null values
: ALTER TABLE "diaries" ALTER "status" SET NOT NULL/home/vagrant/test/db/migrate/20150210031823_change_status_of_diaries.rb:3:in `up'
ActiveRecord::StatementInvalid: PG::NotNullViolation: ERROR: column "status" contains null values
: ALTER TABLE "experiences" ALTER "status" SET NOT NULL
/home/vagrant/test/db/migrate/20150210031823_change_status_of_diaries.rb:3:in `up'
PG::NotNullViolation: ERROR: column "status" contains null values
/home/vagrant/tryjob/db/migrate/20150210031823_change_status_of_diaries.rb:3:in `up'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
MySQLを使っていたときはこれでいけた気がしたんだけどな。PostgreSQLだとこのあたり厳密なんですかね。
結局、change_column_null
の引数の最後にデフォルト値を設定すればいけました。
db/migrate/20150210031823_change_status_of_diaries.rb
class ChangeStatusOfDiaries < ActiveRecord::Migration
def self.up
change_column_null :diaries, :status, false, 0
end
def self.down
change_column_null :diaries, :status, true, nil
end
end