-
Type: Task
-
Resolution: Done
-
Affects Version/s: None
-
Component/s: None
I just spent more than hour debugging an odd issue with an embedded document's after_delete callback where it wasn't
working properly when calling destroy_all on the collection, but did work when calling each(&:destroy).
It's hard to explain without an example, so here's what I used:
<pre># Gemfile is using mongoid's Git HEAD
require 'bundler/setup'
require 'mongoid'
Mongoid.configure do |config|
config.master = Mongo::Connection.new.db('test')
end
class User
include Mongoid::Document
field :name, type: String
embeds_many :favorites
end
class Favorite
include Mongoid::Document
embedded_in :user
field :name, type: String
after_destroy :decrement_count
after_create :increment_count
protected
def decrement_count
FavoriteCount.decrement(self.name)
end
def increment_count
FavoriteCount.increment(self.name)
end
end
class FavoriteCount
include Mongoid::Document
field :name, type: String
field :count, type: Integer, default: 0
def self.decrement(name)
self.update_count(name, -1)
end
def self.increment(name)
self.update_count(name, 1)
end
protected
def self.update_count(name, value)
if fc = self.find_or_initialize_by(name: name)
fc.update_attribute(:count, fc.count + value)
end
end
end
if $0 == FILE
require 'rspec'
describe FavoriteCount do
after do
[User, FavoriteCount].each(&:destroy_all)
end
before do
3.times do |i|
user = User.create(name: "user#
")
user.favorites.create(name: 'mongodb')
end
end
it "updates when calling destroy_all" do
FavoriteCount.where(name: 'mongodb').first.count.should eql(3)
User.last.favorites.destroy_all
- THIS FAILS; expected 2, got 3
FavoriteCount.where(name: 'mongodb').first.count.should eql(2)
end
it "updates when calling each(&:destroy)" do
FavoriteCount.where(name: 'mongodb').first.count.should eql(3)
User.last.favorites.each(&:destroy)
- THIS PASSES
FavoriteCount.where(name: 'mongodb').first.count.should eql(2)
end
end
end</pre>
Both times the callback is being executed, but for some reason only the second way actually has the desired outcome. The only thing I can think of is some kind of weird race condition.