2011-06-06 14:17:44 -04:00
|
|
|
require 'cases/helper'
|
2010-04-16 18:32:06 -04:00
|
|
|
require 'models/topic'
|
2010-06-27 11:17:44 -04:00
|
|
|
require 'models/car'
|
2014-08-09 15:19:02 -04:00
|
|
|
require 'models/aircraft'
|
2010-06-27 11:17:44 -04:00
|
|
|
require 'models/wheel'
|
|
|
|
require 'models/engine'
|
2010-04-16 18:32:06 -04:00
|
|
|
require 'models/reply'
|
|
|
|
require 'models/category'
|
|
|
|
require 'models/categorization'
|
2012-01-16 21:06:14 -05:00
|
|
|
require 'models/dog'
|
|
|
|
require 'models/dog_lover'
|
2012-02-28 13:20:27 -05:00
|
|
|
require 'models/person'
|
|
|
|
require 'models/friendship'
|
2012-10-02 10:30:06 -04:00
|
|
|
require 'models/subscriber'
|
|
|
|
require 'models/subscription'
|
|
|
|
require 'models/book'
|
2010-04-16 18:32:06 -04:00
|
|
|
|
|
|
|
class CounterCacheTest < ActiveRecord::TestCase
|
2012-10-02 10:30:06 -04:00
|
|
|
fixtures :topics, :categories, :categorizations, :cars, :dogs, :dog_lovers, :people, :friendships, :subscribers, :subscriptions, :books
|
2010-04-16 18:32:06 -04:00
|
|
|
|
2010-06-27 11:17:44 -04:00
|
|
|
class ::SpecialTopic < ::Topic
|
2010-04-16 20:01:38 -04:00
|
|
|
has_many :special_replies, :foreign_key => 'parent_id'
|
2014-07-02 21:09:05 -04:00
|
|
|
has_many :lightweight_special_replies, -> { select('topics.id, topics.title') }, :foreign_key => 'parent_id', :class_name => 'SpecialReply'
|
2010-04-16 20:01:38 -04:00
|
|
|
end
|
|
|
|
|
2010-06-27 11:17:44 -04:00
|
|
|
class ::SpecialReply < ::Reply
|
2010-04-16 20:01:38 -04:00
|
|
|
belongs_to :special_topic, :foreign_key => 'parent_id', :counter_cache => 'replies_count'
|
|
|
|
end
|
|
|
|
|
2010-04-16 18:32:06 -04:00
|
|
|
setup do
|
|
|
|
@topic = Topic.find(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "increment counter" do
|
|
|
|
assert_difference '@topic.reload.replies_count' do
|
|
|
|
Topic.increment_counter(:replies_count, @topic.id)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
test "decrement counter" do
|
|
|
|
assert_difference '@topic.reload.replies_count', -1 do
|
|
|
|
Topic.decrement_counter(:replies_count, @topic.id)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
test "reset counters" do
|
|
|
|
# throw the count off by 1
|
|
|
|
Topic.increment_counter(:replies_count, @topic.id)
|
|
|
|
|
|
|
|
# check that it gets reset
|
|
|
|
assert_difference '@topic.reload.replies_count', -1 do
|
|
|
|
Topic.reset_counters(@topic.id, :replies)
|
|
|
|
end
|
|
|
|
end
|
2010-08-14 01:13:00 -04:00
|
|
|
|
2014-03-19 12:24:46 -04:00
|
|
|
test "reset counters by counter name" do
|
|
|
|
# throw the count off by 1
|
|
|
|
Topic.increment_counter(:replies_count, @topic.id)
|
|
|
|
|
|
|
|
# check that it gets reset
|
|
|
|
assert_difference '@topic.reload.replies_count', -1 do
|
|
|
|
Topic.reset_counters(@topic.id, :replies_count)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-05-22 12:25:15 -04:00
|
|
|
test 'reset multiple counters' do
|
|
|
|
Topic.update_counters @topic.id, replies_count: 1, unique_replies_count: 1
|
|
|
|
assert_difference ['@topic.reload.replies_count', '@topic.reload.unique_replies_count'], -1 do
|
2013-05-18 04:12:46 -04:00
|
|
|
Topic.reset_counters(@topic.id, :replies, :unique_replies)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-04-16 20:01:38 -04:00
|
|
|
test "reset counters with string argument" do
|
|
|
|
Topic.increment_counter('replies_count', @topic.id)
|
|
|
|
|
|
|
|
assert_difference '@topic.reload.replies_count', -1 do
|
|
|
|
Topic.reset_counters(@topic.id, 'replies')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
test "reset counters with modularized and camelized classnames" do
|
|
|
|
special = SpecialTopic.create!(:title => 'Special')
|
|
|
|
SpecialTopic.increment_counter(:replies_count, special.id)
|
|
|
|
|
|
|
|
assert_difference 'special.reload.replies_count', -1 do
|
|
|
|
SpecialTopic.reset_counters(special.id, :special_replies)
|
|
|
|
end
|
|
|
|
end
|
2010-04-16 18:32:06 -04:00
|
|
|
|
2012-01-16 21:06:14 -05:00
|
|
|
test "reset counter with belongs_to which has class_name" do
|
2010-06-27 11:17:44 -04:00
|
|
|
car = cars(:honda)
|
|
|
|
assert_nothing_raised do
|
|
|
|
Car.reset_counters(car.id, :engines)
|
|
|
|
end
|
|
|
|
assert_nothing_raised do
|
|
|
|
Car.reset_counters(car.id, :wheels)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-01-16 21:06:14 -05:00
|
|
|
test "reset the right counter if two have the same class_name" do
|
|
|
|
david = dog_lovers(:david)
|
|
|
|
|
|
|
|
DogLover.increment_counter(:bred_dogs_count, david.id)
|
|
|
|
DogLover.increment_counter(:trained_dogs_count, david.id)
|
|
|
|
|
|
|
|
assert_difference 'david.reload.bred_dogs_count', -1 do
|
|
|
|
DogLover.reset_counters(david.id, :bred_dogs)
|
|
|
|
end
|
|
|
|
assert_difference 'david.reload.trained_dogs_count', -1 do
|
|
|
|
DogLover.reset_counters(david.id, :trained_dogs)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-04-16 18:32:06 -04:00
|
|
|
test "update counter with initial null value" do
|
|
|
|
category = categories(:general)
|
|
|
|
assert_equal 2, category.categorizations.count
|
|
|
|
assert_nil category.categorizations_count
|
|
|
|
|
|
|
|
Category.update_counters(category.id, :categorizations_count => category.categorizations.count)
|
|
|
|
assert_equal 2, category.reload.categorizations_count
|
|
|
|
end
|
|
|
|
|
|
|
|
test "update counter for decrement" do
|
|
|
|
assert_difference '@topic.reload.replies_count', -3 do
|
|
|
|
Topic.update_counters(@topic.id, :replies_count => -3)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
test "update counters of multiple records" do
|
|
|
|
t1, t2 = topics(:first, :second)
|
|
|
|
|
|
|
|
assert_difference ['t1.reload.replies_count', 't2.reload.replies_count'], 2 do
|
|
|
|
Topic.update_counters([t1.id, t2.id], :replies_count => 2)
|
|
|
|
end
|
|
|
|
end
|
2012-02-28 13:20:27 -05:00
|
|
|
|
2013-05-22 12:18:43 -04:00
|
|
|
test 'update multiple counters' do
|
|
|
|
assert_difference ['@topic.reload.replies_count', '@topic.reload.unique_replies_count'], 2 do
|
|
|
|
Topic.update_counters @topic.id, replies_count: 2, unique_replies_count: 2
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-09-17 17:57:13 -04:00
|
|
|
test "update other counters on parent destroy" do
|
|
|
|
david, joanna = dog_lovers(:david, :joanna)
|
2013-03-22 22:41:13 -04:00
|
|
|
joanna = joanna # squelch a warning
|
2012-09-17 17:57:13 -04:00
|
|
|
|
|
|
|
assert_difference 'joanna.reload.dogs_count', -1 do
|
|
|
|
david.destroy
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-02-28 13:20:27 -05:00
|
|
|
test "reset the right counter if two have the same foreign key" do
|
|
|
|
michael = people(:michael)
|
|
|
|
assert_nothing_raised(ActiveRecord::StatementInvalid) do
|
2013-03-16 12:32:07 -04:00
|
|
|
Person.reset_counters(michael.id, :friends_too)
|
2012-02-28 13:20:27 -05:00
|
|
|
end
|
|
|
|
end
|
2012-10-02 10:30:06 -04:00
|
|
|
|
|
|
|
test "reset counter of has_many :through association" do
|
|
|
|
subscriber = subscribers('second')
|
|
|
|
Subscriber.reset_counters(subscriber.id, 'books')
|
|
|
|
Subscriber.increment_counter('books_count', subscriber.id)
|
|
|
|
|
|
|
|
assert_difference 'subscriber.reload.books_count', -1 do
|
|
|
|
Subscriber.reset_counters(subscriber.id, 'books')
|
|
|
|
end
|
|
|
|
end
|
2013-03-15 06:22:01 -04:00
|
|
|
|
2014-03-19 12:24:46 -04:00
|
|
|
test "the passed symbol needs to be an association name or counter name" do
|
2013-03-15 06:22:01 -04:00
|
|
|
e = assert_raises(ArgumentError) do
|
2014-03-19 12:24:46 -04:00
|
|
|
Topic.reset_counters(@topic.id, :undefined_count)
|
2013-03-15 06:22:01 -04:00
|
|
|
end
|
2014-03-19 12:24:46 -04:00
|
|
|
assert_equal "'Topic' has no association called 'undefined_count'", e.message
|
2013-03-15 06:22:01 -04:00
|
|
|
end
|
2014-07-02 21:09:05 -04:00
|
|
|
|
|
|
|
test "reset counter works with select declared on association" do
|
|
|
|
special = SpecialTopic.create!(:title => 'Special')
|
|
|
|
SpecialTopic.increment_counter(:replies_count, special.id)
|
|
|
|
|
|
|
|
assert_difference 'special.reload.replies_count', -1 do
|
|
|
|
SpecialTopic.reset_counters(special.id, :lightweight_special_replies)
|
|
|
|
end
|
|
|
|
end
|
2015-01-26 12:50:46 -05:00
|
|
|
|
|
|
|
test "counters are updated both in memory and in the database on create" do
|
|
|
|
car = Car.new(engines_count: 0)
|
|
|
|
car.engines = [Engine.new, Engine.new]
|
|
|
|
car.save!
|
|
|
|
|
|
|
|
assert_equal 2, car.engines_count
|
|
|
|
assert_equal 2, car.reload.engines_count
|
|
|
|
end
|
2015-01-26 14:37:29 -05:00
|
|
|
|
|
|
|
test "counter caches are updated in memory when the default value is nil" do
|
|
|
|
car = Car.new(engines_count: nil)
|
|
|
|
car.engines = [Engine.new, Engine.new]
|
|
|
|
car.save!
|
|
|
|
|
|
|
|
assert_equal 2, car.engines_count
|
|
|
|
assert_equal 2, car.reload.engines_count
|
|
|
|
end
|
2014-08-09 15:19:02 -04:00
|
|
|
|
|
|
|
test "update counters in a polymorphic relationship" do
|
|
|
|
aircraft = Aircraft.create!
|
|
|
|
|
|
|
|
assert_difference 'aircraft.reload.wheels_count' do
|
|
|
|
aircraft.wheels << Wheel.create!
|
|
|
|
end
|
|
|
|
|
|
|
|
assert_difference 'aircraft.reload.wheels_count', -1 do
|
|
|
|
aircraft.wheels.first.destroy
|
|
|
|
end
|
|
|
|
end
|
2010-04-16 18:32:06 -04:00
|
|
|
end
|