1対多のアソシエーション

2020.8.21

アソシエーション(Association)とは

関連を使えば、DB上の紐付けを前提にして、モデルクラス同士の紐付けを定義することができる。

これによって、オブジェクト指向に沿ったやり方で、関連するデータにアクセスすることが可能になる。

アソシエーションは紐付けの際に必ず定義しなければならないわけでも、必ずセット(has_oneとbelong_toなど)で定義しなければならないわけでもない。

ユーザーが複数のタスクを抱えている場合を考える

いわゆる1対多の関係

Userが複数の Taskを持っているので(User has many tasks)、

class User < ApplicationRecord
  has_many: tasks  # Task の複数形
end

Task は一つの User に属しているので(Task belongs to a User)、

class Task < ApplicationRecord
  belongs_to: user  # User の単数形
end

たったこれだけで、Railsは「 Taskは、 user_idを外部キーとして抱えている」ということを認識してくれる。(※外部キーは モデル名_id とする必要あり)

アソシエーションしたデータの受け取り方

ユーザーが持っているタスク」を取得

@user.tasks

 →複数のタスクが格納された配列が返る

このタスクを持っているユーザー」を取得

@task.user

 →ユーザーが返る

アソシエーションを使用しない場合との比較

新規作成処理では...

アソシエーションを使用しない場合

@task = Task.create(text: "本を返す", user_id: @user.id)

アソシエーションを使用する場合

@task = @user.tasks.create(text: "本を返す")

取得処理では...

アソシエーションを使用しない場合

@user = User.find(1)
@task = Task.where(user_id: @user.id)  # いちいち外部キーを指定

アソシエーションを使用する場合

@user = User.find(1)
@tasks = @user.tasks

このように、アソシエーションを使用すると外部キーの指定が不要になり、直感的な記述ができる。

削除処理では...

アソシエーションを使用しない場合

@tasks = Task.where(user_id: @user.id)
@tasks.each do |task|
  task.destroy
end
@user.destroy

アソシエーションを使用する場合

@user.destroy

この記述だけで、Railsが@userに関連する全タスクをまとめて削除してくれる

参考

アソシエーションを図解形式で徹底的に理解しよう!

【初心者向け】丁寧すぎるRails『アソシエーション』チュートリアル【幾ら何でも】【完璧にわかる】🎸 - Qiita