Skip to content

Commit

Permalink
Adding ability to find by array of ids
Browse files Browse the repository at this point in the history
  • Loading branch information
durran committed Jan 23, 2010
1 parent 90a0eae commit 22d2a0d
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 23 deletions.
24 changes: 16 additions & 8 deletions lib/mongoid/criteria.rb
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,9 @@ def in(attributes = {})
# <tt>criteria.id("4ab2bc4b8ad548971900005c")</tt>
#
# Returns: <tt>self</tt>
def id(object_id)
@selector[:_id] = object_id; self
def id(*args)
(args.flatten.size > 1) ? self.in(:_id => args.flatten) : (@selector[:_id] = *args)
self
end

# Create the new +Criteria+ object. This will initialize the selector
Expand Down Expand Up @@ -410,12 +411,8 @@ def skip(value = 0)
def self.translate(*args)
klass = args[0]
params = args[1] || {}
if params.is_a?(String)
document = new(klass).id(params).one
if Mongoid.raise_not_found_error
raise Errors::DocumentNotFound.new(klass, params) unless document
end
return document
unless params.is_a?(Hash)
return id_criteria(klass, params)
end
return new(klass).where(params.delete(:conditions) || {}).extras(params)
end
Expand Down Expand Up @@ -472,5 +469,16 @@ def update_selector(attributes, operator)
attributes.each { |key, value| @selector[key] = { operator => value } }; self
end

class << self
# Return a criteria or single document based on an id search.
def id_criteria(klass, params)
criteria = new(klass).id(params)
result = params.is_a?(String) ? criteria.one : criteria.entries
if Mongoid.raise_not_found_error
raise Errors::DocumentNotFound.new(klass, params) if result.blank?
end
return result
end
end
end
end
6 changes: 3 additions & 3 deletions lib/mongoid/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ module Errors #:nodoc
# Raised when querying the database for a document by a specific id which
# does not exist.
class DocumentNotFound < RuntimeError
def initialize(klass, identifier)
@klass, @identifier = klass, identifier
def initialize(klass, ids)
@klass, @identifier = klass, ids.is_a?(Array) ? ids.join(", ") : ids
end
def message
"Document not found for class #{@klass} and id #{@identifier}"
"Document not found for class #{@klass} and id(s) #{@identifier}"
end
end

Expand Down
25 changes: 25 additions & 0 deletions spec/integration/mongoid/finders_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
describe "#find" do

before do
@documents = []
@document = Person.create(:title => "Mrs.", :ssn => "another")
3.times do |n|
@documents << Person.create(:title => "Mr.", :ssn => "#{n}22")
end
end

after do
Expand All @@ -32,6 +36,27 @@

end

context "with an array of ids as args" do

context "when the documents are found" do

it "returns an array of the documents" do
@people = Person.find(@documents.map(&:id))
@people.should == @documents
end

end

context "when no documents found" do

it "raises an error" do
lambda { Person.find(["11", "21", "31"]) }.should raise_error
end

end

end

end

end
64 changes: 52 additions & 12 deletions spec/unit/mongoid/criteria_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1112,6 +1112,7 @@

it "creates a criteria for a string" do
@criteria.expects(:one).returns(@document)
@document.expects(:blank? => false)
Mongoid::Criteria.translate(Person, @id)
end

Expand All @@ -1128,6 +1129,33 @@

context "multiple arguments" do

context "when an array of ids" do

before do
@ids = []
@documents = []
3.times do
@ids << Mongo::ObjectID.new.to_s
@documents << stub
end
@collection = stub
Person.expects(:collection).returns(@collection)
end

it "returns an ids criteria" do
@collection.expects(:find).with(
{ :_type =>
{ "$in" =>
["Doctor", "Person"]
},
:_id =>
{ "$in" => @ids }
}, {}).returns([{ "_id" => "4", "title" => "Sir", "_type" => "Person" }])
@criteria = Mongoid::Criteria.translate(Person, @ids)
end

end

context "when Person, :conditions => {}" do

before do
Expand Down Expand Up @@ -1200,7 +1228,8 @@

it "adds the clause to the selector" do
@criteria.where(:title => "Title", :text => "Text")
@criteria.selector.should == { :_type => { "$in" => ["Doctor", "Person"] }, :title => "Title", :text => "Text" }
@criteria.selector.should ==
{ :_type => { "$in" => ["Doctor", "Person"] }, :title => "Title", :text => "Text" }
end

end
Expand All @@ -1211,7 +1240,8 @@

it "returns those matching an all clause" do
@criteria.where(:title.all => ["Sir"])
@criteria.selector.should == { :_type => { "$in" => ["Doctor", "Person"] }, :title => { "$all" => ["Sir"] } }
@criteria.selector.should ==
{ :_type => { "$in" => ["Doctor", "Person"] }, :title => { "$all" => ["Sir"] } }
end

end
Expand All @@ -1220,7 +1250,8 @@

it "returns those matching an exists clause" do
@criteria.where(:title.exists => true)
@criteria.selector.should == { :_type => { "$in" => ["Doctor", "Person"] }, :title => { "$exists" => true } }
@criteria.selector.should ==
{ :_type => { "$in" => ["Doctor", "Person"] }, :title => { "$exists" => true } }
end

end
Expand All @@ -1229,7 +1260,8 @@

it "returns those matching a gt clause" do
@criteria.where(:age.gt => 30)
@criteria.selector.should == { :_type => { "$in" => ["Doctor", "Person"] }, :age => { "$gt" => 30 } }
@criteria.selector.should ==
{ :_type => { "$in" => ["Doctor", "Person"] }, :age => { "$gt" => 30 } }
end

end
Expand All @@ -1238,7 +1270,8 @@

it "returns those matching a gte clause" do
@criteria.where(:age.gte => 33)
@criteria.selector.should == { :_type => { "$in" => ["Doctor", "Person"] }, :age => { "$gte" => 33 } }
@criteria.selector.should ==
{ :_type => { "$in" => ["Doctor", "Person"] }, :age => { "$gte" => 33 } }
end

end
Expand All @@ -1247,7 +1280,8 @@

it "returns those matching an in clause" do
@criteria.where(:title.in => ["Sir", "Madam"])
@criteria.selector.should == { :_type => { "$in" => ["Doctor", "Person"] }, :title => { "$in" => ["Sir", "Madam"] } }
@criteria.selector.should ==
{ :_type => { "$in" => ["Doctor", "Person"] }, :title => { "$in" => ["Sir", "Madam"] } }
end

end
Expand All @@ -1256,7 +1290,8 @@

it "returns those matching a lt clause" do
@criteria.where(:age.lt => 34)
@criteria.selector.should == { :_type => { "$in" => ["Doctor", "Person"] }, :age => { "$lt" => 34 } }
@criteria.selector.should ==
{ :_type => { "$in" => ["Doctor", "Person"] }, :age => { "$lt" => 34 } }
end

end
Expand All @@ -1265,7 +1300,8 @@

it "returns those matching a lte clause" do
@criteria.where(:age.lte => 33)
@criteria.selector.should == { :_type => { "$in" => ["Doctor", "Person"] }, :age => { "$lte" => 33 } }
@criteria.selector.should ==
{ :_type => { "$in" => ["Doctor", "Person"] }, :age => { "$lte" => 33 } }
end

end
Expand All @@ -1274,7 +1310,8 @@

it "returns those matching a ne clause" do
@criteria.where(:age.ne => 50)
@criteria.selector.should == { :_type => { "$in" => ["Doctor", "Person"] }, :age => { "$ne" => 50 } }
@criteria.selector.should ==
{ :_type => { "$in" => ["Doctor", "Person"] }, :age => { "$ne" => 50 } }
end

end
Expand All @@ -1283,7 +1320,8 @@

it "returns those matching a nin clause" do
@criteria.where(:title.nin => ["Esquire", "Congressman"])
@criteria.selector.should == { :_type => { "$in" => ["Doctor", "Person"] }, :title => { "$nin" => ["Esquire", "Congressman"] } }
@criteria.selector.should ==
{ :_type => { "$in" => ["Doctor", "Person"] }, :title => { "$nin" => ["Esquire", "Congressman"] } }
end

end
Expand All @@ -1292,7 +1330,8 @@

it "returns those matching a size clause" do
@criteria.where(:aliases.size => 2)
@criteria.selector.should == { :_type => { "$in" => ["Doctor", "Person"] }, :aliases => { "$size" => 2 } }
@criteria.selector.should ==
{ :_type => { "$in" => ["Doctor", "Person"] }, :aliases => { "$size" => 2 } }
end

end
Expand All @@ -1305,7 +1344,8 @@

it "adds the $where clause to the selector" do
@criteria.where("this.date < new Date()")
@criteria.selector.should == { :_type => { "$in" => ["Doctor", "Person"] }, "$where" => "this.date < new Date()" }
@criteria.selector.should ==
{ :_type => { "$in" => ["Doctor", "Person"] }, "$where" => "this.date < new Date()" }
end

end
Expand Down
13 changes: 13 additions & 0 deletions spec/unit/mongoid/finders_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,19 @@

end

context "when an array of ids is passed in" do

before do
@ids = []
3.times { @ids << Mongo::ObjectID.new.to_s }
end

it "delegates to the criteria" do

end

end

context "when nil passed in" do

it "raises an error" do
Expand Down

0 comments on commit 22d2a0d

Please sign in to comment.