我的模型如下所示:
class User < ActiveRecord::Base
has_many :created_games, class_name: 'Game', foreign_key: 'challenger_id'
has_many :challenged_games, class_name: 'Game', foreign_key: 'opponent_id'
end
class Game < ActiveRecord::Base
belongs_to :challenger, :class_name => 'User'
belongs_to :opponent, :class_name => 'User'
end
用户故事 作为用户,我希望查看可以挑战并与之一起玩游戏的用户列表。如果我们之间存在现有游戏,我不能向用户挑战新游戏。
范围
我有一个类方法如下:
def self.challeangable_for(user_id)
challengeable_users = User.joins("LEFT JOIN ( SELECT games.challenger_id, games.opponent_id FROM games where games.challenger_id = #{user_id} OR games.opponent_id = #{user_id}) as g on g.challenger_id = users.id or g.opponent_id = users.id WHERE g.challenger_id is null and g.opponent_id is null")
end
这会正确生成“可挑战用户”列表,但我似乎无法链接此查询。例如,如果我这样做User.challengeable_users(1).where(gender: 'm')
,rails 会将 WHERE 子句附加到末尾,并且查询将失败:
SQLite3::SQLException: near "WHERE": syntax error: SELECT "users".* FROM "users" LEFT JOIN ( SELECT games.challenger_id, games.opponent_id FROM games where games.challenger_id = 1 OR games.opponent_id = 1) as g on g.challenger_id = users.id or g.opponent_id = users.id WHERE g.challenger_id is null and g.opponent_id is null WHERE "users"."gender" = 'm' ORDER BY users.created_at DESC
而且,它又长又丑。有没有更好的办法?我尝试使用“包含”,但我没有找到一种方法 tp 指定不同的(非标准)外键加入?
我意识到我有点专注于生成 LEFT JOIN 查询的解决方案。另一种解决方案是生成 EXISTS IN 查询,但我不知道如何编写。