migrateでカラムに外部キーを追加して、モデルを関連づける【Day 4/30 2nd】
こんにちは、たわらです。
本記事は、railsでmigrateする際に、カラムにモデルの関連づけのために外部キーを追加する方法を整理します。
前提としては、ユーザーと、そのユーザーの複数の投稿(tweet)を紐付けたい、ということです。
外部キーをテーブルに追加する
そのためには、新しく作成するtweetsテーブルに user_id というカラムを追加して、投稿を所有しているユーザーの id を格納するようにします。
このような場合では、referenceというデータ型を使用して外部キーのカラムを追加します。
tweetsテーブルを作成するマイグレーションファイルを、こんな感じに記述します。
db/migrate/hogehogehogehogehoge.rb
class CreateTweets < ActiveRecord::Migration[5.2]
def change
create_table :tweets do |t|
t.string :text, null: false
t.references :user, foreign_key: true, null: false
t.timestamps
end
end
end
t.references :user, foreign_key: true ここですね。
t.referencees :user で、user_idというカラムを作成してくれます。そしてindexを自動で付与してくれます。indexにより検索が楽になります。
ただし、データの読み込みや取得が早くなるメリットがあるかわりに、書き込みの速度が遅くなるというデメリットがあるみたいです。
これだけだと、外部キー制約はつかないので、
foreign_key: true をつけます。
また、既存のテーブルに外部キーを追加したい場合は次のようになります。
class AddColumn < ActiveRecord::Migration[5.0]
def change
add_reference :tweets, :user, foreign_key: true
end
end
ちなみに、、、
null: false と記述することで、NOT NULL制約をつけることができます。データベースカラムの値にNULLを格納したくない場合に、つまり、あるモデルの属性の値が必ず入らなければいけないと期待するときに、このような制約をつけます。
モデルを関連づける
で、UserモデルとTweetモデルを関連付けます。
この場合、ひとりのユーザーに対して、複数の投稿(tweet)を紐付けづけるので、こんなふうになります。
tweet.rb
class Tweet < ApplicationRecord
belongs_to :user
end
ひとりのユーザーに紐づくので、複数形ではなく単数形でuserと記述するのですね。
ユーザーは複数の投稿をするので、ひとりのユーザーが複数の投稿を持ちます。なので、、、
user.rb
class User < ApplicationRecord
has_many :tweets
end
tweetsと複数形で記述するのですね。直感的です。
オブジェクトの取得の仕方
このようにモデルを関連づけることで、必要なオブジェクトを呼び出すメソッドが使えるようになります。
つまり具体的には、あるユーザーの投稿一覧が欲しいな、というときには、
user.tweetsというメソッドを使えば投稿オブジェクトが取得できます。
また、この投稿に紐づいてるユーザーをオブジェクトとして欲しいな、というときには、
tweet.userというメソッドで取得することができるようになります。
最後に
他にもモデルの関連はあるらしいのですが、それはまた今度です。
読んでくださったかた、ありがとうございます。
参考文献
・reference型や外部キー
・モデルの関連