1

我的模型如下所示:

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 查询,但我不知道如何编写。

4

1 回答 1

0

是的,您可以稍微重写一下:

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").where("g.opponent_id is null")

然后你可以进一步应用你的性别条件。

于 2013-03-13T16:37:37.283 回答