Mongoid criteria that returns nothing
mongoid, ruby-on-rails
Solution
What version of Mongoid are you on? Because when I try `Model.none` it returns an empty set:
Model.none
Model.none.count # => 0
`none` was added in version 4. If you can’t update to that version, you could try integrating the change. These methods at at line 309 in `/lib/mongoid.criteria.rb` need to be defined:
def none
@none = true and self
end
def empty_and_chainable?
!!@none
end
`Mongoid::Contextual#create_context` also needs to be changed:
def create_context
return None.new(self) if empty_and_chainable?
embedded ? Memory.new(self) : Mongo.new(self)
end
Then you can include `/lib/mongoid/contextual/none.rb'.
EDIT: this Gist backports `.none` to Mongoid 3:
module Mongoid
class Criteria
def none
@none = true and self
end
def empty_and_chainable?
!!@none
end
end
module Contextual
class None
include ::Enumerable
# Previously included Queryable, which has been extracted in v4
attr_reader :collection, :criteria, :klass
def blank?
!exists?
end
alias :empty? :blank?
attr_reader :criteria, :klass
def ==(other)
other.is_a?(None)
end
def each
if block_given?
[].each { |doc| yield(doc) }
self
else
to_enum
end
end
def exists?; false; end
def initialize(criteria)
@criteria, @klass = criteria, criteria.klass
end
def last; nil; end
def length
entries.length
end
alias :size :length
end
private
def create_context
return None.new(self) if empty_and_chainable?
embedded ? Memory.new(self) : Mongo.new(self)
end
end
module Finders
delegate :none, to: :with_default_scope
end
end
Problem
I need to create a mongoid criteria which will return nothing. I couldn't find any "none"-kind of method, so I'm doing Model.where(id: nil) or Model.any_in(id: nil) instead. However this is not nice, and will also query the db. I would like to add my own selector to mongoid that will return an empty result without even querying the db (such as Model.none()), but don't know where/how to do it. Can somebody help? Note: I need this because the caller might chain the criteria without having to know it's already empty.