Skip to content

Commit

Permalink
Implement proper delete_if for embeds_many.
Browse files Browse the repository at this point in the history
[ close #2324 ]
[ close #2339 ]
  • Loading branch information
durran committed Sep 8, 2012
1 parent e8518c9 commit 9823a83
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -26,6 +26,8 @@ For instructions on upgrading to newer versions, visit
Band.where(name: "Depeche Mode").pluck(:_id)
Band.where(name: "Tool").pluck(:likes)

* \#2324 Embeds many relations now properly handle `delete_if`.

* \#2317 Added `Document.first_or_create` and `Criteria#first_or_create`.
This will return the first matching document or create one with additional
attributes if one does not exist. (incorvia)
Expand Down
22 changes: 22 additions & 0 deletions lib/mongoid/relations/embedded/many.rb
Expand Up @@ -165,6 +165,28 @@ def delete_all(conditions = {})
remove_all(conditions, :delete)
end

# Delete all the documents for which the provided block returns true.
#
# @example Delete the matching documents.
# person.addresses.delete_if do |doc|
# doc.state = "GA"
# end
#
# @return [ Many, Enumerator ] The relation or an enumerator if no
# block was provided.
#
# @since 3.1.0
def delete_if
if block_given?
target.each do |doc|
delete(doc) if yield(doc)
end
self
else
super
end
end

# Destroy all the documents in the association whilst running callbacks.
#
# @example Destroy all documents from the relation.
Expand Down
106 changes: 106 additions & 0 deletions spec/mongoid/relations/embedded/many_spec.rb
Expand Up @@ -1560,6 +1560,112 @@ class TrackingIdValidationHistory
end
end

describe "#delete_if" do

let(:person) do
Person.create
end

context "when the documents are new" do

let!(:address_one) do
person.addresses.build(street: "Bond")
end

let!(:address_two) do
person.addresses.build(street: "Upper")
end

context "when a block is provided" do

let!(:deleted) do
person.addresses.delete_if do |doc|
doc.street == "Bond"
end
end

it "removes the matching documents" do
person.addresses.size.should eq(1)
end

it "removes from the unscoped" do
person.addresses.send(:_unscoped).size.should eq(1)
end

it "returns the relation" do
deleted.should eq(person.addresses)
end
end

context "when no block is provided" do

let!(:deleted) do
person.addresses.delete_if
end

it "returns an enumerator" do
deleted.should be_a(Enumerator)
end
end
end

context "when the documents persisted" do

let!(:address_one) do
person.addresses.create(street: "Bond")
end

let!(:address_two) do
person.addresses.create(street: "Upper")
end

context "when a block is provided" do

let!(:deleted) do
person.addresses.delete_if do |doc|
doc.street == "Bond"
end
end

it "deletes the matching documents" do
person.addresses.count.should eq(1)
end

it "deletes the matching documents from the db" do
person.reload.addresses.count.should eq(1)
end

it "returns the relation" do
deleted.should eq(person.addresses)
end
end
end

context "when the documents are empty" do

context "when a block is provided" do

let!(:deleted) do
person.addresses.delete_if do |doc|
doc.street == "Bond"
end
end

it "deletes the matching documents" do
person.addresses.count.should eq(0)
end

it "deletes all the documents from the db" do
person.reload.addresses.count.should eq(0)
end

it "returns the relation" do
deleted.should eq(person.addresses)
end
end
end
end

[ :delete_all, :destroy_all ].each do |method|

describe "##{method}" do
Expand Down

0 comments on commit 9823a83

Please sign in to comment.