-
Type:
Task
-
Resolution: Done
-
Affects Version/s: None
-
Component/s: None
-
None
-
None
-
None
-
None
-
None
-
None
-
None
Hi folks,
I'm having trouble using the .changes and .changed methods to track dirty attributes in my Rails app. After loading an object and accessing one of it's array or hash attributes, the changed array contains that key—even though it has not actually changed. Calling field_changed? returns false, but the attributes are still listed in the changed array.
I have a Mongoid document class with several fields:
field :title, :type => String, :default => I18n.t('pop.untitled') field :contents, :default => [] field :background_color, :type => String, :default => 'ffffff'
I don't have any ActiveRecord callbacks that could be messing with the values of those fields. In my code, I instantiate a new instance of this class using Find:
@target_revision = PopRevision.find(head_revision_id) binding.pry
As soon as the revision object has been loaded, I can jump to the pry interface and demonstrate the problem. First, I verify that after the Find, the object has no changes. Then I access the contents field. Immediately, the changes array updates to include the "contents" attribute. This is strange, because I have not modified the contents in any way by accessing them (there is no method called contents), and the contents array is not getting set to the default value of [].
[1] pry(#<Pop>)> @target_revision.changes => {} [2] pry(#<Pop>)> @target_revision.contents => [{"title"=>"New Text", "body"=> "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.", "type"=>"Text", "layout"=> {"4fe23928dd02dcfdcb000014"=> {"size"=>"m", "region"=>0, "x"=>0, "y"=>0, "height"=>160, "sortOrder"=>0}}, "id"=>0}] [3] pry(#<Pop>)> @target_revision.changes => {"contents"=>nil}
Unfortunately, this gets a little weirder. The changed array matches what is shown in the changes hash. However, when I ask specifically about whether the contents attribute is dirty, I get false:
[4] pry(#<Pop>)> @target_revision.changed => ["contents"] [5] pry(#<Pop>)> @target_revision.contents_changed? => false
I can repeat this test with a non-array type and it works as expected. It appears that only array and hash types exhibit this behavior:
[1] pry(#<Pop>)> @target_revision.changes => {} [2] pry(#<Pop>)> @target_revision.title => "Colab pop!" [3] pry(#<Pop>)> @target_revision.changes => {} [4] pry(#<Pop>)> @target_revision.background_color => "ffffff" [5] pry(#<Pop>)> @target_revision.changes => {}
In my app, I'm looking at the changed attributes and determining whether to do a save! or a timeless.save!, and since accessing the contents field is marking it in the changes array, the app is updating timestamps on each save. Any idea what might be causing this problem? Any chance I'm mis-using the changes array and I should be doing this another way?
Thanks, keep up the great work on mongoid!