ラムダを持つスコープがあり、引数の値に応じて引数を取る場合、一致するものはないことを知っているかもしれませんが、空の配列ではなくリレーションを返したいです:
scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : [] }
私が本当に欲しいのは、「all」の反対の「none」メソッドです。このメソッドは、連鎖することができるリレーションを返しますが、クエリは短絡します。
Rails 4には「正しい」メカニズムがあります:
>> Model.none
=> #<ActiveRecord::Relation []>
「id」列を必要とせず、idが0の行がないことを前提としない、より移植性の高いソリューション:
scope :none, where("1 = 0")
もっと「正しい」方法を探しています。
Rails 4では、ActiveRecord::NullRelation
などの呼び出しからチェーン可能なPost.none
が返されます。
それも、連鎖メソッドも、データベースへのクエリを生成しません。
コメントによると:
返されるActiveRecord :: NullRelationは、Relationを継承し、Null Objectパターンを実装します。 null動作が定義されたオブジェクトであり、データベースをクエリせずに常にレコードの空の配列を返します。
ソースコード を参照してください。
「none」というスコープを追加できます。
scope :none, where(:id => nil).where("id IS NOT ?", nil)
空のActiveRecord :: Relationが得られます
また、初期化子のActiveRecord :: Baseに追加することもできます(必要な場合)。
class ActiveRecord::Base
def self.none
where(arel_table[:id].eq(nil).and(arel_table[:id].not_eq(nil)))
end
end
このようなものを手に入れる方法はたくさんありますが、コードベースに保管するのが最善ではありません。空のActiveRecord :: Relationを短時間保証する必要があることをリファクタリングして見つけるときに、スコープ:noneを使用しました。
scope :none, limit(0)
スコープが連鎖している可能性があるため、危険なソリューションです。
User.none.first
最初のユーザーを返します。使用する方が安全です
scope :none, where('1 = 0')
私はこれが他のオプションに見える方法を好むと思う:
scope :none, limit(0)
このようなものにつながる:
scope :users, lambda { |ids| ids.present? ? where("user_id IN (?)", ids) : limit(0) }
スコープを使用:
scope:for_users、lambda {| users | users.any? ? where( "user_id IN(?)"、users.map(&:id).join( '、')):スコープ}
ただし、次の方法でコードを簡素化することもできます。
scope:for_users、lambda {| users | where(:user_id => users.map(&:id))if users.any? }
空の結果が必要な場合は、これを使用します(if条件を削除します):
scope:for_users、lambda {| users | where(:user_id => users.map(&:id))}
それは可能ですので、それは:
scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : User.none }
http://apidock.com/Rails/v4.0.2/ActiveRecord/QueryMethods/none
私が間違っている場合は修正してください。
バリアントもありますが、これらはすべてdbにリクエストを送信しています
where('false')
where('null')