私のモデルは次のようになります。
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クエリを生成するものですが、それを作成する方法がわかりません。