references型:カラム型。別のモデルに対する参照を意味している。
SQLite3ではnot null制約を付与しつつカラムのデフォルト値を指定しない場合、カラムの追加でエラーになってしまいます。NG例とOK例を用いて説明しています。
# NG
class AddNicknameToUsers < ActiveRecord::Migration[6.0]
def change
add_column :users, :nickname, :string, null: false
end
end
# OK
class AddNicknameToUsers < ActiveRecord::Migration[6.0]
def change
add_column :users, :nickname, :string, null: false, default: 'sample'
end
end
# OK
class AddNicknameToUsers < ActiveRecord::Migration[6.0]
def change
add_column :users, :nickname, :string
change_column :users, :nickname, :string, null: false
end
end
パーフェクト Ruby on Rails p60の例での説明
まず最初にBookモデルにPublisherモデルのリレーションを付与するために新しいマイグレーションファイルを作成しました。
Sayo-MacBook-Pro:book_admin SAYO$ bin/rails g migration AddPublisherIdToBooks publisher:references
Running via Spring preloader in process 49467
invoke active_record
create db/migrate/20211213105113_add_publisher_id_to_books.rb
作成されたファイルの中身を見ていきます。
class AddPublisherIdToBooks < ActiveRecord::Migration[6.0]
def change
add_reference :books, :publisher, null: false, foreign_key: true
end
end
add_reference :books, :publisher
の部分はbooksテーブルにpublisherというreferences型のカラムを追加する、という意味です。
null: false
not null制約を有効にする
foreign_key: true
外部キー制約をつける(references型でカラムを追加しても外部キーとして扱われるわけではなく、foreign_key: trueとすることで外部キーとして扱われるようになる)
しかし上記のコードのままだとSQLite3ではnot null制約とデフォルト値を指定していないのでエラーが出ます。なのでカラムの追加とnot null制約を別々の行で定義します。
def change
add_reference :books, :publisher, foreign_key: true
#rails g migration時にreferencesをつけた事により外部キーであるforeign_keyが生成されており、この行でpublisher_idが作られます。(注:publisher_idとこの行で書いてしまうとpublisher_id_idとなってしまいます。)
change_column :books, :publisher_id, :integer, null: false
#ここで1行目に生成されたpublisher_idにnull: falseをつけることでnot null制約を付与しています。
end
schemaファイルを見てみます。
t.integer "publisher_id", null: false
not null制約がついているのがわかります。