我通过User
模型定义的Friendship
模型之间存在关系。 (ROR 4)
class User < ActiveRecord::Base
has_many :friendships, ->(object) { where('user_id = :id OR friend_id = :id', id: object.id) }
has_many :friends, ->(object) { where(friendships: {status: 'accepted'}).where('user_id = :id OR friend_id = :id', id: object.id) }, through: :friendships, source: :friend
has_many :requested_friends, -> { where(friendships: {status: 'pending'}) }, through: :friendships, source: :friend
end
class Friendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, class_name: 'User'
def self.request(user, friend)
unless user == friend or find_friendship(user, friend) != nil
create(user: user, friend: friend, status: 'pending')
end
end
def self.find_friendship(user, friend)
ids = [user.id, friend.id]
where(user_id: ids, friend_id: ids).first
end
end
然而,由于产生了SQL查询,这不起作用并且我的测试失败了。
> user.friendships
查询:
SELECT "friendships".* FROM "friendships"
WHERE "friendships"."user_id" = ?
AND (user_id = 1 OR friend_id = 1) [["user_id", 1]]
AND 之前 WHERE 的一部分“杀死”我的实际位置。我通过制作实例方法做了一个解决方法:
def friendships
self.class
.select('friendships.* FROM `friendships`')
.where('user_id = :id OR friend_id = :id', id)
end
有没有办法可以删除我的实例方法并修改has_many关系来生成我想要的SQL?
> Friendship.request(user, friend)
> friend.requested_friends
查询:
SELECT "users".* FROM "users"
INNER JOIN "friendships" ON "users"."id" = "friendships"."friend_id"
WHERE "friendships"."status" = 'pending'
AND "friendships"."user_id" = ?
AND (user_id = 2 OR friend_id = 2) [["user_id", 2]]
显然这不是我需要的,所以我通过删除has_many :requested_friends
并制作实例方法来解决方法:
def requested_friends
self.class
.joins('JOIN `friendships` friendships ON users.id = friendships.user_id')
.where('friendships.status = ?', 'pending')
.where('friendships.friend_id = ?', id)
end
有没有什么方法可以修改我的has_many :requested_friends
关系来生成与我的实例方法相同的SQL?
答案 0 :(得分:0)
非常混乱 - 我会做这样的事情:
#app/models/user.rb
Class User < ActiveRecord::Base
has_many :friendships, class_name: "user_friendships", association_foreign_key: "user_id", foreign_key: "friend_id",
has_many :friends, class_name: "User", through: :friendships
end
#app/models/user_friendship.rb
Class UserFriendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, class_name: "User"
end
你有一个如下所示的联接表:
user_friendships
id | user_id | friend_id | other | info | created_at | updated_at
这应该有用(我不确定自我引用关联)。如果是,它将允许您致电:
@user.friends
我希望这有帮助吗?
您可能也会受益于this gem
答案 1 :(得分:0)
使用带有条件的has_many
方法无法实现所需的SQL。原因是传递给方法的块只是附加条件,在标准查询之上检查user_id = ?
。
相反,您可以稍微简化实例方法
def friendships
Friendship.where('user_id = :id or friend_id = :id', id)
end