jwood/tenacity — Issue #34: t_has_many relationship nullifying child association fields on update (AR has_many Mongoid)
Author: abradner
Created: 2011-12-06 01:58:12+00:00
State: open

I'm having trouble pinning down exactly what's causing it, but when I update an AR record, tenacity seems to be nullifying all of the id fields in a t_has_many related Mongoid model.

I've attached some large blobs of output below. As far as I can tell, tenacity seems to be calling

```
Tenacity::Associations::HasMany::ClassMethods._t_clear_old_associations(record#StorageLocation(id: i...,...)
```
for no reason (see frame 17 in the debug log at the bottom)

For context:
app/controllers/management/storage_locations_controller.rb

```ruby
class Management::StorageLocationsController < ApplicationController

def update
if @storage_location.update_attributes(params[:storage_location])
redirect_to management_storage_locations_path, :notice => "The storage location was successfully updated."
else
render :edit
end
end
end
```

app/models/storage_location.rb

```ruby
class StorageLocation < ActiveRecord::Base
include Tenacity
belongs_to :system
t_has_many :file_types, :dependent => :destroy

#validations
end
```

app/models/file_type.rb

```ruby
class FileType
include Mongoid::Document
include Mongoid::Timestamps
include Tenacity

field :name, :type => String
field :content, :type => String
field :extensions, :type => String #change to array
field :versioning, :type => Boolean

t_belongs_to :system
t_belongs_to :storage_location
has_many :import_mappings
has_many :raw_files
embeds_many :file_metadata_schemas

before_save :debugger
```

Logs:

Server Log

```
Started PUT "/management/storage_locations/1" for 127.0.0.1 at Tue Dec 06 12:20:49 +1100 2011
Processing by Management::StorageLocationsController#update as HTML
Parameters: {"commit"=>"Update Storage location", "authenticity_token"=>"H7X2Z/oV0m2Gt2Qro99xe0ZIXvTMQdTud+toEAx+YQA=", "utf8"=>"✓", "id"=>"1", "storage_location"=>{"name"=>"Raw Blob A", "location"=>"/tmp", "storage_type"=>"fs", "system_id"=>"1"}}
MONGODB webdb_development['system.namespaces'].find({})
System Load (0.3ms) SELECT "systems".* FROM "systems" ORDER BY name
StorageLocation Load (0.2ms) SELECT "storage_locations".* FROM "storage_locations" WHERE "storage_locations"."id" = ? LIMIT 1 [["id", "1"]]
(0.2ms) SELECT 1 FROM "storage_locations" WHERE (LOWER("storage_locations"."name") = LOWER('Raw Blob A') AND "storage_locations"."id" != 1 AND "storage_locations"."system_id" = 1) LIMIT 1
MONGODB webdb_development['system.namespaces'].find({})
MONGODB webdb_development['file_types'].find({"storage_location_id"=>1}).sort(_idasc)
MONGODB webdb_development['file_types'].find({"storage_location_id"=>1})
System Load (0.2ms) SELECT "systems".* FROM "systems" WHERE "systems"."id" = 1 LIMIT 1
MONGODB webdb_development['file_types'].update({"_id"=>BSON::ObjectId('4edd6948eb98e3f32f000007')}, {"$set"=>{"updated_at"=>Tue Dec 06 01:21:01 UTC 2011, "storage_location_id"=>nil}})
MONGODB webdb_development['file_types'].find({"storage_location_id"=>1})
Redirected to http://localhost:3000/management/storage_locations
Completed 302 Found in 21841ms
```

Debugger Trace. Top of the trace is the before_save in FileType, bottom is update_attributes in StorageLocationsController

```
--> #0 FileType._run_save_callbacks(key#NilClass)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activesupport-3.1.1/lib/active_support/callbacks.rb:416
#1 Kernel.send(kind#Symbol)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activesupport-3.1.1/lib/active_support/callbacks.rb:81
#2 ActiveSupport::Callbacks.to_s(kind#Symbol)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activesupport-3.1.1/lib/active_support/callbacks.rb:81
#3 Proc.run_callbacks
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/mongoid-2.3.3/lib/mongoid/callbacks.rb:42
#4 Mongoid::Callbacks.run_cascading_callbacks(children#Array, kind#Symbol)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/mongoid-2.3.3/lib/mongoid/callbacks.rb:67
#5 Mongoid::Callbacks.run_callbacks(kind#Symbol)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/mongoid-2.3.3/lib/mongoid/callbacks.rb:41
#6 Mongoid::Persistence::Modification.prepare
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/mongoid-2.3.3/lib/mongoid/persistence/modification.rb:23
#7 Mongoid::Persistence::Operations::Update.persist
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/mongoid-2.3.3/lib/mongoid/persistence/operations/update.rb:43
#8 Mongoid::Persistence.update(options#Hash)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/mongoid-2.3.3/lib/mongoid/persistence.rb:86
#9 Mongoid::Persistence.save(options#Hash)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/mongoid-2.3.3/lib/mongoid/persistence.rb:151
#10 Tenacity::OrmExt::Mongoid::InstanceMethods._t_save_if_dirty
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/tenacity-0.5.3/lib/tenacity/orm_ext/mongoid.rb:117
#11 Tenacity::Associations::HasMany::ClassMethods.save_associate(associate#FileType,...)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/tenacity-0.5.3/lib/tenacity/associations/has_many.rb:122
#12 Mongo::Cursor._t_clear_old_associations
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/tenacity-0.5.3/lib/tenacity/associations/has_many.rb:117
#13 Mongoid::Cursor.each
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/mongoid-2.3.3/lib/mongoid/cursor.rb:48
#14 Mongoid::Contexts::Mongo.iterate
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/mongoid-2.3.3/lib/mongoid/contexts/mongo.rb:212
#15 Kernel.each
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/mongoid-2.3.3/lib/mongoid/criteria.rb:143
#16 Mongoid::Criteria.each
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/mongoid-2.3.3/lib/mongoid/criteria.rb:143
#17 Tenacity::Associations::HasMany::ClassMethods._t_clear_old_associations(record#StorageLocation(id: i...,...)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/tenacity-0.5.3/lib/tenacity/associations/has_many.rb:115
#18 Tenacity::Associations::HasMany::ClassMethods._t_save_associates(record#StorageLocation(id: i...,...)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/tenacity-0.5.3/lib/tenacity/associations/has_many.rb:106
#19 StorageLocation._callback_after_23973(key#NilClass)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/tenacity-0.5.3/lib/tenacity/orm_ext/activerecord.rb:90
#20 StorageLocation._run_save_callbacks(key#NilClass)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activesupport-3.1.1/lib/active_support/callbacks.rb:413
#21 Kernel.send(kind#Symbol)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activesupport-3.1.1/lib/active_support/callbacks.rb:81
#22 ActiveSupport::Callbacks.to_s(kind#Symbol)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activesupport-3.1.1/lib/active_support/callbacks.rb:81
#23 ActiveRecord::Callbacks.create_or_update
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activerecord-3.1.1/lib/active_record/callbacks.rb:264
#24 ActiveRecord::Persistence.save
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activerecord-3.1.1/lib/active_record/persistence.rb:37
#25 ActiveRecord::Validations.save(options#Hash)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activerecord-3.1.1/lib/active_record/validations.rb:50
#26 ActiveRecord::AttributeMethods::Dirty.save
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activerecord-3.1.1/lib/active_record/attribute_methods/dirty.rb:22
#27 ActiveRecord::ConnectionAdapters::DatabaseStatements.save(options#Hash)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activerecord-3.1.1/lib/active_record/transactions.rb:241
#28 ActiveRecord::Transactions::ClassMethods.transaction(options#Hash)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activerecord-3.1.1/lib/active_record/transactions.rb:208
#29 ActiveRecord::Transactions.with_transaction_returning_status
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activerecord-3.1.1/lib/active_record/transactions.rb:293
#30 ActiveRecord::Transactions.save
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activerecord-3.1.1/lib/active_record/transactions.rb:241
#31 ActiveRecord::Transactions.save
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activerecord-3.1.1/lib/active_record/transactions.rb:240
#32 ActiveRecord::ConnectionAdapters::DatabaseStatements.update_attributes(options#Hash,...)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activerecord-3.1.1/lib/active_record/persistence.rb:163
#33 ActiveRecord::Transactions::ClassMethods.transaction(options#Hash)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activerecord-3.1.1/lib/active_record/transactions.rb:208
#34 ActiveRecord::Transactions.with_transaction_returning_status
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activerecord-3.1.1/lib/active_record/transactions.rb:293
#35 ActiveRecord::Persistence.update_attributes(attributes#ActiveSupport::HashWi...,...)
at line /Users/abradner/.rvm/gems/ree-1.8.7-2011.03@webdb/gems/activerecord-3.1.1/lib/active_record/persistence.rb:161
#36 Management::StorageLocationsController.[]
at line /Users/abradner/Dropbox/code/usyd/webdb/app/controllers/management/storage_locations_controller.rb:27
```