Skip to content

Commit

Permalink
Adding concat and difference to criteria
Browse files Browse the repository at this point in the history
  • Loading branch information
durran committed Jan 18, 2010
1 parent e13988b commit f6d55f1
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 1 deletion.
15 changes: 15 additions & 0 deletions lib/mongoid/criteria.rb
Expand Up @@ -21,6 +21,18 @@ class Criteria

attr_reader :klass, :options, :selector

# Concatinate the criteria with another enumerable. If the other is a
# +Criteria+ then it needs to get the collection from it.
def +(other)
collect + (other.is_a?(Criteria) ? other.collect : other)
end

# Returns the difference between the criteria and another enumerable. If
# the other is a +Criteria+ then it needs to get the collection from it.
def -(other)
collect - (other.is_a?(Criteria) ? other.collect : other)
end

# Returns true if the supplied +Enumerable+ or +Criteria+ is equal to the results
# of this +Criteria+ or the criteria itself.
#
Expand Down Expand Up @@ -499,6 +511,9 @@ def sum(field)
grouped(:sum, field.to_s, SUM_REDUCE)
end

alias :to_a :collect
alias :to_ary :collect

# Translate the supplied arguments into a +Criteria+ object.
#
# If the passed in args is a single +String+, then it will
Expand Down
2 changes: 2 additions & 0 deletions lib/mongoid/extensions/array/accessors.rb
Expand Up @@ -9,6 +9,8 @@ def update(attributes)
delete_if { |e| attributes["_id"] && (e["_id"] == attributes["_id"]) }
self.<< attributes
end

alias :merge! :update
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/mongoid/extensions/hash/accessors.rb
Expand Up @@ -21,7 +21,7 @@ def remove(key, attrs)
def insert(key, attrs)
elements = self[key]
if elements
elements.update(attrs)
elements.merge!(attrs)
else
self[key] = key.singular? ? attrs : [attrs]
end
Expand Down
18 changes: 18 additions & 0 deletions spec/integration/mongoid/associations_spec.rb
Expand Up @@ -113,6 +113,24 @@

end

context "when a has-one to has-many" do

before do
@person = Person.new(:title => "Sir")
@name = Name.new(:first_name => "Syd")
@person.name = @name
@person.save
end

it "persists all the associations properly" do
from_db = Person.find(@person.id)
translation = Translation.new(:language => "fr")
from_db.name.translations << translation
from_db.attributes[:name][:translations].should_not be_nil
end

end

context "when a has-many to has-many" do

before do
Expand Down
7 changes: 7 additions & 0 deletions spec/spec_helper.rb
Expand Up @@ -173,13 +173,20 @@ class Name
field :last_name
field :parent_title
key :first_name, :last_name
has_many :translations
belongs_to :person, :inverse_of => :name

def set_parent=(set = false)
self.parent_title = person.title if set
end
end

class Translation
include Mongoid::Document
field :language
belongs_to :name, :inverse_of => :translations
end

class Comment
include Mongoid::Document
include Mongoid::Versioning
Expand Down
105 changes: 105 additions & 0 deletions spec/unit/mongoid/criteria_spec.rb
Expand Up @@ -7,6 +7,111 @@
@canvas_criteria = Mongoid::Criteria.new(Canvas)
end

describe "#+" do

before do
@sir = Person.new(:title => "Sir")
@madam = Person.new(:title => "Madam")
@canvas = Canvas.new
end

context "when the criteria has not been executed" do

before do
@collection = mock
@cursor = stub(:count => 1, :collect => [ @sir, @madam ])
Person.expects(:collection).returns(@collection)
@collection.expects(:find).returns(@cursor)
end

it "executes the criteria and concats the results" do
results = @criteria + [ @canvas ]
results.should == [ @sir, @madam, @canvas ]
end

end

context "when the criteria has been executed" do

before do
@criteria.instance_variable_set(:@collection, [ @sir, @madam ])
end

it "concats the results" do
results = @criteria + [ @canvas ]
results.should == [ @sir, @madam, @canvas ]
end

end

context "when the other is a criteria" do

before do
@criteria.instance_variable_set(:@collection, [ @sir, @madam ])
@canvas_criteria.instance_variable_set(:@collection, [ @canvas ])
end

it "concats the results" do
results = @criteria + @canvas_criteria
results.should == [ @sir, @madam, @canvas ]
end

end

end

describe "#-" do

before do
@sir = Person.new(:title => "Sir")
@madam = Person.new(:title => "Madam")
end

context "when the criteria has not been executed" do

before do
@collection = mock
@cursor = stub(:count => 1, :collect => [ @sir, @sir, @madam ])
Person.expects(:collection).returns(@collection)
@collection.expects(:find).returns(@cursor)
end

it "executes the criteria and returns the difference" do
results = @criteria - [ @sir ]
results.should == [ @madam ]
end

end

context "when the criteria has been executed" do

before do
@criteria.instance_variable_set(:@collection, [@sir, @sir, @madam])
end

it "returns the difference" do
results = @criteria - [ @sir ]
results.should == [ @madam ]
end

end

context "when the other is a criteria" do

before do
@criteria.instance_variable_set(:@collection, [@sir, @sir, @madam])
@canvas_criteria.instance_variable_set(:@collection, [@sir])
end

it "returns the difference" do
results = @criteria - @canvas_criteria
results.should == [ @madam ]
end

end

end

describe "#[]" do

before do
Expand Down

0 comments on commit f6d55f1

Please sign in to comment.