-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Minor - P4
-
Affects Version/s: 5.2.1
-
Component/s: Associations, Persistence
-
None
-
Environment:ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin16]
Rails 4.2.10
Counter cache is not correctly updated (i.e. decremented) when the relation is nullified using update_attribute
After looking in the code, it seems that CounterCache update callback is broken in this case, because the outermost 'if' block prevents the execution when the updated attribute is null (whereas the callback is executed after the update)
Issue found in v5, but by code reading (no test) I would say that the bug is also present in v6 and v7 branches
Here is some steps to reproduce, everything goes well (association, re-association) until final attribute update (de-association)
[1] pry(main)> class B [1] pry(main)* include Mongoid::Document [1] pry(main)* end => B [2] pry(main)> class A [2] pry(main)* include Mongoid::Document [2] pry(main)* belongs_to :b, counter_cache: true [2] pry(main)* end => {:relation=>Mongoid::Relations::Referenced::In, :extend=>nil, :inverse_class_name=>"A", :name=>:b, :counter_cache=>true, :validate=>false} [3] pry(main)> class B [3] pry(main)* include Mongoid::Document [3] pry(main)* has_many :as [3] pry(main)* field :as_count, type: Integer, default: 0 [3] pry(main)* end => #<Mongoid::Fields::Standard:0x007f9d1ff71368 @default_val=0, @label=nil, @name="as_count", @options={:type=>Integer, :default=>0, :klass=>B}, @pre_processed=true> [4] pry(main)> a = A.create => #<A _id: 5a7b0efdce735f25ce2ae942, b_id: nil> [5] pry(main)> b1 = B.create => #<B _id: 5a7b0f04ce735f25ce2ae943, as_count: 0> [6] pry(main)> a.update_attribute(:b, b1) => true [7] pry(main)> b1.reload.as => [#<A _id: 5a7b0efdce735f25ce2ae942, b_id: BSON::ObjectId('5a7b0f04ce735f25ce2ae943')>] [8] pry(main)> b1.as_count => 1 [9] pry(main)> b2 = B.create => #<B _id: 5a7b0f37ce735f25ce2ae944, as_count: 0> [10] pry(main)> a.update_attribute(:b, b2) => true [11] pry(main)> b1.reload.as => [] [12] pry(main)> b1.as_count => 0 [13] pry(main)> b2.reload.as => [#<A _id: 5a7b0efdce735f25ce2ae942, b_id: BSON::ObjectId('5a7b0f37ce735f25ce2ae944')>] [14] pry(main)> b2.as_count => 1 [15] pry(main)> a.update_attribute(:b, nil) => true [16] pry(main)> b2.reload.as => [] [17] pry(main)> b2.as_count => 1 [18] pry(main)> b2.reset_counters(:as) => [:as] [19] pry(main)> b2.as_count => 0