Skip to content
30 changes: 30 additions & 0 deletions lib/mongoid/criteria/findable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,36 @@ def multiple_from_db(ids)
ids.empty? ? [] : from_database(ids)
end

# Return true if any documents exist in the criteria.
#
# @example Determine if any documents exist
# criteria.any?
#
# @return [ true | false ] If any documents exist.
def any?
limit(1).count > 0
end

# Return true if only one document exists in the criteria.
#
# @example Determine if only one document exists
# criteria.one?
#
# @return [ true | false ] If only one document exists.
def one?
limit(2).count == 1
end

# Return true if more than one document exists in the criteria.
#
# @example Determine if many documents exist
# criteria.many?
#
# @return [ true | false ] If many documents exist.
def many?
limit(2).count > 1
end

private

# Get the finder used to generate the id query.
Expand Down
3 changes: 3 additions & 0 deletions lib/mongoid/findable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module Findable
# directly from the class level.
def_delegators :with_default_scope,
:aggregates,
:any?,
:avg,
:create_with,
:distinct,
Expand All @@ -40,10 +41,12 @@ module Findable
:fourth!,
:includes,
:last!,
:many?,
:map_reduce,
:max,
:min,
:none,
:one?,
:pick,
:pluck,
:raw,
Expand Down
206 changes: 206 additions & 0 deletions spec/mongoid/criteria/findable_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1302,6 +1302,212 @@
end
end

describe "#any?" do
context "when called on criteria" do
let!(:band) do
Band.create!(name: "Depeche Mode")
end

let!(:band_two) do
Band.create!(name: "Radiohead")
end

context "when documents exist" do

let(:criteria) do
Band.all
end

it "returns true" do
expect(criteria.any?).to be true
end
end

context "when no documents exist" do

let(:criteria) do
Band.where(name: "Nonexistent Band")
end

it "returns false" do
expect(criteria.any?).to be false
end
end
end

context "when called on class" do
context "with documents" do
before do
Band.create!(name: "New Band")
end

it "returns true" do
expect(Band.any?).to be true
end
end

context "with no documents" do
before do
Band.delete_all
end
it "returns false" do
expect(Band.any?).to be false
end
end
end
end

describe "#one?" do
context "when called on criteria" do
let!(:band) do
Band.create!(name: "Depeche Mode")
end

let!(:band_two) do
Band.create!(name: "Radiohead")
end

context "when one document exists in criteria" do
let(:criteria) do
Band.where(name: "Depeche Mode")
end

it "returns true" do
expect(criteria.one?).to be true
end
end

context "when multiple documents exist in criteria" do
let(:criteria) do
Band.all
end

it "returns false" do
expect(criteria.one?).to be false
end
end

context "when no documents exist in criteria" do
let(:criteria) do
Band.where(name: "Nonexistent Band")
end

it "returns false" do
expect(criteria.one?).to be false
end
end
end

context "when called on class" do
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let me know if this needs to be moved elsewhere or isnt needed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this should probably be moved to spec/mongoid/findable_spec.rb, since it's no longer implemented on Mongoid::Criteria.

When you move these, you should also make sure the tests invoke the new methods directly on the model classes, rather than on criteria instances. E.g.

let(:model) { Band } # instance of :criteria

# ...

expect(model.any?).to be true

context "with no documents" do
before do # can maybe delete this - not sure how cleanup works here
Band.delete_all
end

it "returns false" do
expect(Band.one?).to be false
end
end

context "with one document" do
before do
Band.create!(name: "Another Band")
end

it "returns true" do
expect(Band.one?).to be true
end
end

context "with multiple documents" do
before do
Band.create!(name: "New Band")
Band.create!(name: "Yet Another Band")
end

it "returns false" do
expect(Band.one?).to be false
end
end
end
end

describe "#many?" do
context "when called on criteria" do
let!(:band) do
Band.create!(name: "Depeche Mode")
end

let!(:band_two) do
Band.create!(name: "Radiohead")
end

context "when multiple documents exist in criteria" do
let(:criteria) do
Band.all
end

it "returns true" do
expect(criteria.many?).to be true
end
end

context "when one document exists in criteria" do
let(:criteria) do
Band.where(name: "Depeche Mode")
end

it "returns false" do
expect(criteria.many?).to be false
end
end

context "when no documents exist in criteria" do
let(:criteria) do
Band.where(name: "Nonexistent Band")
end

it "returns false" do
expect(criteria.many?).to be false
end
end

end

context "when called on class" do
context "with no documents" do
before do
Band.delete_all
end

it "returns false" do
expect(Band.many?).to be false
end
end

context "with one document" do
before do
Band.create!(name: "Another Band")
end

it "returns false" do
expect(Band.many?).to be false
end
end

context "with multiple documents" do
before do
Band.create!(name: "New Band")
Band.create!(name: "Yet Another Band")
end

it "returns true" do
expect(Band.many?).to be true
end
end
end
end

describe '#from_database_selector' do
let(:criteria) { Mongoid::Criteria.new(Band) }
let(:result) { criteria.send(:from_database_selector, [1]) }
Expand Down
Loading