Как добиться многого через отношения между пользователями
Я создаю систему сопоставления между пользователями, изначально она имела и принадлежит многим ассоциациям, но из-за некоторых проверок и дополнительных данных, которые мне нужны для этой таблицы соединений, мне нужно иметь модель для этой таблицы и изменить ее на множество.
has_and_belongs_to_many(:likes,
class_name: :User,
join_table: :user_likes,
foreign_key: :user_liker_id,
association_foreign_key: :user_liked_id)
has_and_belongs_to_many(:likeds,
class_name: :User,
join_table: :user_likes,
foreign_key: :user_liked_id,
association_foreign_key: :user_liker_id)
Это старая реализация, которую нужно преобразовать в has_many через. Как вы можете видеть, с этим я могу получить всех пользователей, которые мне понравились, и пользователей, которые мне понравились. Я создал UserLike
модель, но у меня нет никакого успеха в том, чтобы сделать ее работоспособной внутри пользовательской модели. То, что я уже попробовал, следующее:
user.rb
has_many :user_likes
has_many :likes, through: :user_likes, foreign_key: :user_liked_id
has_many :likeds, through: :user_likes, foreign_key: :user_liker_id
user_like.rb
class UserLike < ApplicationRecord
belongs_to :user
end
Эта реализация вызывает следующее исключение:
ActiveRecord:: HasManyThroughSourceAssociationNotFoundError: Не удалось найти ассоциацию (и) источника "like" или: likes в модели UserLike. Попробуйте 'has_many:likes,:through =>:user_likes,:source => '. Это один из user или user_likes?
Я не знаю, что мне здесь не хватает, любая помощь будет оценена:)
2 ответа
При создании таблицы соединения, которая дважды объединяет одну и ту же таблицу, необходимо две отдельные ассоциации, поскольку пользователь может использовать любой внешний ключ:
class User < ApplicationRecord
has_many :likes_as_liker,
class_name: 'Like',
foreign_key: 'liker_id'
has_many :likes_as_liked,
class_name: 'Like',
foreign_key: 'liked_id'
end
class Like < ApplicationRecord
belongs_to :liker, class_name: 'User'
belongs_to :liked, class_name: 'User'
end
Сделав две наши ассоциации has_many, мы можем начать создавать косвенные ассоциации:
class User < ApplicationRecord
has_many :likes_as_liker,
class_name: 'Like',
foreign_key: 'liker_id'
has_many :likes_as_liked,
class_name: 'Like',
foreign_key: 'liked_id'
has_many :likers,
through: :likes_as_liked
has_many :liked_users,
through: :likes_as_liker,
source: :liked
end
Который работает отлично:
irb(main):002:0> u.likers
User Load (2.8ms) SELECT "users".* FROM "users" INNER JOIN "likes" ON "users"."id" = "likes"."liker_id" WHERE "likes"."liked_id" = $1 LIMIT $2 [["liked_id", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy []>
irb(main):003:0> u.liked_users
User Load (1.3ms) SELECT "users".* FROM "users" INNER JOIN "likes" ON "users"."id" = "likes"."liked_id" WHERE "likes"."liker_id" = $1 LIMIT $2 [["liker_id", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy []>
В соответствии с описанием, упомянутым в посте, вы пытаетесь найти пользователей, которым понравился мой пост, и пользователей, которые мне понравились.
Ниже упомянутый код не говорит рельсам, что лайки и лайки на самом деле являются пользователями.
has_many :user_likes
has_many :likes, through: :user_likes, foreign_key: :user_liked_id
has_many :likeds, through: :user_likes, foreign_key: :user_liker_id
Изменить его ниже
has_many :user_likes
has_many :likes, through: :user_likes, foreign_key: :user_liked_id, source: :liked
has_many :likeds, through: :user_likes, foreign_key: :user_liker_id, source: :liked
Наилучший подход определяет класс вместе с именем класса, чтобы рельсы знали, в каком классе отображается этот внешний ключ при указании имен настраиваемых отношений
Если имя вашей ассоциации отличается от имени, используемого в:through, вы должны определить параметр источника. Если вы посмотрите на сообщение об исключении, оно явно попросит вас сделать это.
Надеюсь, что это отвечает на вопрос.