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

ユーザーストーリーユーザー として、ゲームをプレイするために挑戦できるユーザーのリストを見たいです。私たちの間に既存のゲームが存在する場合、新しいゲームをユーザーに要求することはできません。

スコープ

私は次のように1つのクラスメソッドを持っています:

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

また、それは長くて醜いです。もっと良い方法はありますか?'includes'を使用してみましたが、参加する別の(非標準の)外部キーを指定する方法が見つかりませんでしたか?

LEFTJOINクエリを生成するソリューションに固執していることに気づきました。別の解決策は、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 に答える