mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
reset_counters() was crashing when there were multiple belongs_to associations with the same foreign key.
This closes #5200.
This commit is contained in:
parent
ce0dd56183
commit
ff0d9b93b9
8 changed files with 36 additions and 2 deletions
|
@ -1,5 +1,11 @@
|
||||||
## Rails 4.0.0 (unreleased) ##
|
## Rails 4.0.0 (unreleased) ##
|
||||||
|
|
||||||
|
* Fix `reset_counters` when there are multiple `belongs_to` association with the
|
||||||
|
same foreign key and one of them have a counter cache.
|
||||||
|
Fixes #5200.
|
||||||
|
|
||||||
|
*Dave Desrochers*
|
||||||
|
|
||||||
* `serialized_attributes` and `_attr_readonly` become class method only. Instance reader methods are deprecated.
|
* `serialized_attributes` and `_attr_readonly` become class method only. Instance reader methods are deprecated.
|
||||||
|
|
||||||
*kennyj*
|
*kennyj*
|
||||||
|
|
|
@ -25,7 +25,7 @@ module ActiveRecord
|
||||||
foreign_key = has_many_association.foreign_key.to_s
|
foreign_key = has_many_association.foreign_key.to_s
|
||||||
child_class = has_many_association.klass
|
child_class = has_many_association.klass
|
||||||
belongs_to = child_class.reflect_on_all_associations(:belongs_to)
|
belongs_to = child_class.reflect_on_all_associations(:belongs_to)
|
||||||
reflection = belongs_to.find { |e| e.foreign_key.to_s == foreign_key }
|
reflection = belongs_to.find { |e| e.foreign_key.to_s == foreign_key && e.options[:counter_cache].present? }
|
||||||
counter_name = reflection.counter_cache_column
|
counter_name = reflection.counter_cache_column
|
||||||
|
|
||||||
stmt = unscoped.where(arel_table[primary_key].eq(object.id)).arel.compile_update({
|
stmt = unscoped.where(arel_table[primary_key].eq(object.id)).arel.compile_update({
|
||||||
|
|
|
@ -8,9 +8,11 @@ require 'models/category'
|
||||||
require 'models/categorization'
|
require 'models/categorization'
|
||||||
require 'models/dog'
|
require 'models/dog'
|
||||||
require 'models/dog_lover'
|
require 'models/dog_lover'
|
||||||
|
require 'models/person'
|
||||||
|
require 'models/friendship'
|
||||||
|
|
||||||
class CounterCacheTest < ActiveRecord::TestCase
|
class CounterCacheTest < ActiveRecord::TestCase
|
||||||
fixtures :topics, :categories, :categorizations, :cars, :dogs, :dog_lovers
|
fixtures :topics, :categories, :categorizations, :cars, :dogs, :dog_lovers, :people, :friendships
|
||||||
|
|
||||||
class ::SpecialTopic < ::Topic
|
class ::SpecialTopic < ::Topic
|
||||||
has_many :special_replies, :foreign_key => 'parent_id'
|
has_many :special_replies, :foreign_key => 'parent_id'
|
||||||
|
@ -109,4 +111,11 @@ class CounterCacheTest < ActiveRecord::TestCase
|
||||||
Topic.update_counters([t1.id, t2.id], :replies_count => 2)
|
Topic.update_counters([t1.id, t2.id], :replies_count => 2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "reset the right counter if two have the same foreign key" do
|
||||||
|
michael = people(:michael)
|
||||||
|
assert_nothing_raised(ActiveRecord::StatementInvalid) do
|
||||||
|
Person.reset_counters(michael.id, :followers)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
4
activerecord/test/fixtures/friendships.yml
vendored
Normal file
4
activerecord/test/fixtures/friendships.yml
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Connection 1:
|
||||||
|
id: 1
|
||||||
|
person_id: 1
|
||||||
|
friend_id: 2
|
3
activerecord/test/fixtures/people.yml
vendored
3
activerecord/test/fixtures/people.yml
vendored
|
@ -4,15 +4,18 @@ michael:
|
||||||
primary_contact_id: 2
|
primary_contact_id: 2
|
||||||
number1_fan_id: 3
|
number1_fan_id: 3
|
||||||
gender: M
|
gender: M
|
||||||
|
followers_count: 1
|
||||||
david:
|
david:
|
||||||
id: 2
|
id: 2
|
||||||
first_name: David
|
first_name: David
|
||||||
primary_contact_id: 3
|
primary_contact_id: 3
|
||||||
number1_fan_id: 1
|
number1_fan_id: 1
|
||||||
gender: M
|
gender: M
|
||||||
|
followers_count: 1
|
||||||
susan:
|
susan:
|
||||||
id: 3
|
id: 3
|
||||||
first_name: Susan
|
first_name: Susan
|
||||||
primary_contact_id: 2
|
primary_contact_id: 2
|
||||||
number1_fan_id: 1
|
number1_fan_id: 1
|
||||||
gender: F
|
gender: F
|
||||||
|
followers_count: 1
|
||||||
|
|
4
activerecord/test/models/friendship.rb
Normal file
4
activerecord/test/models/friendship.rb
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
class Friendship < ActiveRecord::Base
|
||||||
|
belongs_to :friend, class_name: 'Person'
|
||||||
|
belongs_to :follower, foreign_key: 'friend_id', class_name: 'Person', counter_cache: :followers_count
|
||||||
|
end
|
|
@ -8,6 +8,8 @@ class Person < ActiveRecord::Base
|
||||||
has_many :posts_with_no_comments, -> { includes(:comments).where('comments.id is null').references(:comments) },
|
has_many :posts_with_no_comments, -> { includes(:comments).where('comments.id is null').references(:comments) },
|
||||||
:through => :readers, :source => :post
|
:through => :readers, :source => :post
|
||||||
|
|
||||||
|
has_many :followers, foreign_key: 'friend_id', class_name: 'Friendship'
|
||||||
|
|
||||||
has_many :references
|
has_many :references
|
||||||
has_many :bad_references
|
has_many :bad_references
|
||||||
has_many :fixed_bad_references, -> { where :favourite => true }, :class_name => 'BadReference'
|
has_many :fixed_bad_references, -> { where :favourite => true }, :class_name => 'BadReference'
|
||||||
|
|
|
@ -270,6 +270,11 @@ ActiveRecord::Schema.define do
|
||||||
t.string :name
|
t.string :name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table :friendships, :force => true do |t|
|
||||||
|
t.integer :friend_id
|
||||||
|
t.integer :person_id
|
||||||
|
end
|
||||||
|
|
||||||
create_table :goofy_string_id, :force => true, :id => false do |t|
|
create_table :goofy_string_id, :force => true, :id => false do |t|
|
||||||
t.string :id, :null => false
|
t.string :id, :null => false
|
||||||
t.string :info
|
t.string :info
|
||||||
|
@ -476,6 +481,7 @@ ActiveRecord::Schema.define do
|
||||||
t.references :number1_fan
|
t.references :number1_fan
|
||||||
t.integer :lock_version, :null => false, :default => 0
|
t.integer :lock_version, :null => false, :default => 0
|
||||||
t.string :comments
|
t.string :comments
|
||||||
|
t.integer :followers_count, :default => 0
|
||||||
t.references :best_friend
|
t.references :best_friend
|
||||||
t.references :best_friend_of
|
t.references :best_friend_of
|
||||||
t.timestamps
|
t.timestamps
|
||||||
|
|
Loading…
Reference in a new issue