3

これらの2つのコードは、それぞれMicropostモデル内のリレーションを返します。

scope :including_replies, lambda { |user| where("microposts.in_reply_to = ?", user.id)}

def self.from_users_followed_by(user)
  followed_user_ids = user.followed_user_ids
  where("user_id IN (?) OR user_id = ?", followed_user_ids, user)
end

実行するr1 = Micropost.including_replies(user)と、次のSQLで2つの結果との関係が得られます。

SELECT `microposts`.* FROM `microposts` WHERE (microposts.in_reply_to = 102) ORDER BY 
microposts.created_at DESC

実行するr2 = Micropost.from_users_followed_by(user)と、次のSQLで1つの結果との関係が得られます。

SELECT `microposts`.* FROM `microposts` WHERE (user_id IN (NULL) OR user_id = 102) ORDER 
BY microposts.created_at DESC

このように関係をマージすると、r3 = r1.merge(r2)結果はゼロになりましたが、3つを期待していました。これは、SQLが次のようになっているためです。

SELECT `microposts`.* FROM `microposts` WHERE (microposts.in_reply_to = 102) AND 
(user_id IN (NULL) OR user_id = 102) ORDER BY microposts.created_at DESC

今私が必要としているのは、マージされた関係の代わり(microposts.in_reply_to = 102) OR (user_id IN (NULL) OR user_id = 102) に必要なことです。ORAND

これを行う方法はありますか?

4

1 に答える 1

1

Railsと直接ではありません。Railsは、ActiveRelation(スコープ)オブジェクトを。とマージする方法を公開していませんOR。その理由は、ActiveRelationには、条件(WHERE句で説明されているもの)だけでなく、結合や、マージがOR明確に定義されていないその他のSQL句も含まれている可能性があるためです。

これは、Arelを直接使用するか(ActiveRelationがその上に構築されている)、DSLを介してArel機能を公開するSqueelを使用することができます(これはより便利な場合があります)Squeelを使用する場合でも、ActiveRelationsをマージできないことは重要です。ただし、Squeelは、(他のSQL句なしで)条件を表すSifterも提供しており、これを使用できますただし、スコープをふるいとして書き直す必要があります。

于 2012-09-07T03:55:38.663 に答える