2-2-2

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: falsenot 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: falsenot null制約がついているのがわかります。