2013-03-13 41 views
0

我的模式是這樣的:用'where'鏈接作用域導致附加SQL(未合併)?

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'),軌道將在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查詢的東西,但我不知道該如何寫。

回答

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") 

然後你就可以進一步申請您的性別條件。

+0

太棒了,那有效!我花了這麼多小時,但最後它開始有點合理。謝謝! – rei 2013-03-14 05:07:04