多対多テーブル Modelの書き方を
・お気に入り機能(comment<->favorite_comment<->user)
・フォロー機能(user<->follow_user<->user)
の2つを例にして紹介する。
お気に入り機能
ユーザー(users)がコメント(comments)をお気に入りする
テーブル
・comments
・favoite_comments(中間テーブル)
-comment_id
-user_id
・users
Model
has_many :favorite_comments
has_many :favo_users, class_name: "User", foreign_key: "user_id", through: :favorite_comments, :source 'user', dependent: :delete_all
has_many :favorite_comments
has_many :favo_comments, class_name: "Comment", foreign_key: "comment_id", through: :favorite_comemnts, :source 'user', dependent: :delete_all
belogns_to :comment
belongs_to :user
フォロー機能
ユーザー(from_user)がユーザー(to_user)をフォローする
テーブル
・users
・follow_users(中間テーブル)
-to_user_id
-from_user_id
Model
has_many :follow_users_of_to_user, class_name: 'FollowUser', foreign_key: 'to_user_id', dependent: :delete_all
has_many :friends_of_to_user, through: :follow_users_to_user, source: 'from_user'
has_many :follow_users_of_from_user, class_name: 'FollowUser', foreign_key: 'from_user_id', dependent: :delete_all
has_many :friends_of_from_user, through: :follow_users_from_user, source: 'to_user'
belongs_to :to_user, class_name: 'User', foreign_key: 'to_user_id'
belongs_to :from_user, class_name: 'User', foreign_key: 'from_user_id'
associationのoptionについて
dependent
今回はdependent: :delete_allを使ったが、
時としてこんなエラーになることがある。
Cannot delete or update a parent row: a foreign key constraint fails (`finc_blog_development`.`comments`, CONSTRAINT `fk_rails_35f401eaf6` FOREIGN KEY (`article_id`) REFERENCES `articles` (`id`))
user削除->article削除->comment削除と2段階以上の関連があることが問題だった。
2段階以上の関連があるときは:destroyを使わなければならない。
ただし、1段階の関連のときは、処理速度の速いdelete_allのほうが効率がよい。
つまり、
1段階の関連だけなら処理は速いdelete_allで2段階以上の関連ならdestroyを使えばよい。
through
多対多のモデルで中間テーブルを使うときに登場し、中間テーブルを意識せずに関連データの取得ができるようになる。
has_and_belongs_to_manyを使う方法もあるが、制約が多いのでthroughを使うほうが無難。
class_name, foreign_key, source
多対多の場合、フォロー機能のようにUserモデルだけでフォローする側、フォローされる側の両方の役割を担う必要があり、その関係を示すために使用している。