identity_cache 0.5.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. checksums.yaml +5 -5
  2. data/.github/probots.yml +2 -0
  3. data/.github/workflows/ci.yml +26 -0
  4. data/.gitignore +1 -0
  5. data/.rubocop.yml +5 -0
  6. data/.travis.yml +24 -9
  7. data/CHANGELOG.md +21 -0
  8. data/Gemfile +5 -1
  9. data/README.md +28 -26
  10. data/Rakefile +14 -5
  11. data/dev.yml +9 -16
  12. data/gemfiles/Gemfile.latest-release +6 -0
  13. data/gemfiles/Gemfile.rails-edge +6 -0
  14. data/gemfiles/Gemfile.rails52 +6 -0
  15. data/identity_cache.gemspec +26 -10
  16. data/lib/identity_cache.rb +49 -46
  17. data/lib/identity_cache/belongs_to_caching.rb +12 -40
  18. data/lib/identity_cache/cache_fetcher.rb +6 -5
  19. data/lib/identity_cache/cache_hash.rb +2 -2
  20. data/lib/identity_cache/cache_invalidation.rb +4 -11
  21. data/lib/identity_cache/cache_key_generation.rb +17 -65
  22. data/lib/identity_cache/cache_key_loader.rb +128 -0
  23. data/lib/identity_cache/cached.rb +7 -0
  24. data/lib/identity_cache/cached/association.rb +87 -0
  25. data/lib/identity_cache/cached/attribute.rb +123 -0
  26. data/lib/identity_cache/cached/attribute_by_multi.rb +37 -0
  27. data/lib/identity_cache/cached/attribute_by_one.rb +88 -0
  28. data/lib/identity_cache/cached/belongs_to.rb +93 -0
  29. data/lib/identity_cache/cached/embedded_fetching.rb +41 -0
  30. data/lib/identity_cache/cached/prefetcher.rb +51 -0
  31. data/lib/identity_cache/cached/primary_index.rb +97 -0
  32. data/lib/identity_cache/cached/recursive/association.rb +68 -0
  33. data/lib/identity_cache/cached/recursive/has_many.rb +9 -0
  34. data/lib/identity_cache/cached/recursive/has_one.rb +9 -0
  35. data/lib/identity_cache/cached/reference/association.rb +16 -0
  36. data/lib/identity_cache/cached/reference/has_many.rb +105 -0
  37. data/lib/identity_cache/cached/reference/has_one.rb +100 -0
  38. data/lib/identity_cache/configuration_dsl.rb +53 -215
  39. data/lib/identity_cache/encoder.rb +95 -0
  40. data/lib/identity_cache/expiry_hook.rb +36 -0
  41. data/lib/identity_cache/fallback_fetcher.rb +2 -1
  42. data/lib/identity_cache/load_strategy/eager.rb +28 -0
  43. data/lib/identity_cache/load_strategy/lazy.rb +71 -0
  44. data/lib/identity_cache/load_strategy/load_request.rb +20 -0
  45. data/lib/identity_cache/load_strategy/multi_load_request.rb +27 -0
  46. data/lib/identity_cache/memoized_cache_proxy.rb +127 -58
  47. data/lib/identity_cache/parent_model_expiration.rb +45 -11
  48. data/lib/identity_cache/query_api.rb +128 -394
  49. data/lib/identity_cache/railtie.rb +8 -0
  50. data/lib/identity_cache/record_not_found.rb +6 -0
  51. data/lib/identity_cache/should_use_cache.rb +1 -0
  52. data/lib/identity_cache/version.rb +3 -2
  53. data/lib/identity_cache/with_primary_index.rb +136 -0
  54. data/lib/identity_cache/without_primary_index.rb +24 -3
  55. data/performance/cache_runner.rb +28 -34
  56. data/performance/cpu.rb +3 -2
  57. data/performance/externals.rb +4 -3
  58. data/performance/profile.rb +6 -5
  59. data/railgun.yml +16 -0
  60. metadata +44 -73
  61. data/Gemfile.rails42 +0 -6
  62. data/Gemfile.rails50 +0 -6
  63. data/test/attribute_cache_test.rb +0 -110
  64. data/test/cache_fetch_includes_test.rb +0 -46
  65. data/test/cache_hash_test.rb +0 -14
  66. data/test/cache_invalidation_test.rb +0 -139
  67. data/test/deeply_nested_associated_record_test.rb +0 -19
  68. data/test/denormalized_has_many_test.rb +0 -214
  69. data/test/denormalized_has_one_test.rb +0 -160
  70. data/test/fetch_multi_test.rb +0 -308
  71. data/test/fetch_test.rb +0 -258
  72. data/test/fixtures/serialized_record.mysql2 +0 -0
  73. data/test/fixtures/serialized_record.postgresql +0 -0
  74. data/test/helpers/active_record_objects.rb +0 -106
  75. data/test/helpers/database_connection.rb +0 -72
  76. data/test/helpers/serialization_format.rb +0 -51
  77. data/test/helpers/update_serialization_format.rb +0 -27
  78. data/test/identity_cache_test.rb +0 -29
  79. data/test/index_cache_test.rb +0 -161
  80. data/test/memoized_attributes_test.rb +0 -59
  81. data/test/memoized_cache_proxy_test.rb +0 -107
  82. data/test/normalized_belongs_to_test.rb +0 -107
  83. data/test/normalized_has_many_test.rb +0 -231
  84. data/test/normalized_has_one_test.rb +0 -9
  85. data/test/prefetch_associations_test.rb +0 -379
  86. data/test/readonly_test.rb +0 -109
  87. data/test/recursive_denormalized_has_many_test.rb +0 -131
  88. data/test/save_test.rb +0 -82
  89. data/test/schema_change_test.rb +0 -112
  90. data/test/serialization_format_change_test.rb +0 -16
  91. data/test/test_helper.rb +0 -140
@@ -1,27 +0,0 @@
1
- $LOAD_PATH.unshift File.expand_path("../../../lib", __FILE__)
2
-
3
- require 'logger'
4
- require 'active_record'
5
- require 'memcached_store'
6
- require 'active_support/cache/memcached_store'
7
- require_relative 'serialization_format'
8
- require_relative 'database_connection'
9
- require_relative 'active_record_objects'
10
- require 'identity_cache'
11
-
12
- include SerializationFormat
13
- include ActiveRecordObjects
14
-
15
- DatabaseConnection.setup
16
- DatabaseConnection.drop_tables
17
- DatabaseConnection.create_tables
18
- IdentityCache.logger = Logger.new(nil)
19
- IdentityCache.cache_backend = ActiveSupport::Cache::MemcachedStore.new(
20
- "#{ENV["MEMCACHED_HOST"] || "localhost"}:11211",
21
- :support_cas => true,
22
- )
23
- setup_models
24
- File.open(serialized_record_file, 'w') {|file| serialize(serialized_record, file) }
25
- puts "Serialized record to #{serialized_record_file}"
26
- IdentityCache.cache.clear
27
- teardown_models
@@ -1,29 +0,0 @@
1
- require "test_helper"
2
-
3
- class IdentityCacheTest < IdentityCache::TestCase
4
-
5
- class BadModelBase < ActiveRecord::Base
6
- include IdentityCache
7
- end
8
-
9
- class BadModel < BadModelBase
10
- end
11
-
12
- def test_identity_cache_raises_if_loaded_twice
13
- assert_raises(IdentityCache::AlreadyIncludedError) do
14
- BadModel.class_eval do
15
- include IdentityCache
16
- end
17
- end
18
- end
19
-
20
- def test_should_use_cache_outside_transaction
21
- assert_equal true, IdentityCache.should_use_cache?
22
- end
23
-
24
- def test_should_use_cache_in_transaction
25
- ActiveRecord::Base.transaction do
26
- assert_equal false, IdentityCache.should_use_cache?
27
- end
28
- end
29
- end
@@ -1,161 +0,0 @@
1
- require "test_helper"
2
-
3
- class IndexCacheTest < IdentityCache::TestCase
4
- NAMESPACE = IdentityCache::CacheKeyGeneration::DEFAULT_NAMESPACE
5
-
6
- def setup
7
- super
8
- @record = Item.new
9
- @record.id = 1
10
- @record.title = 'bob'
11
- end
12
-
13
- def test_fetch_with_garbage_input
14
- Item.cache_index :title, :id
15
-
16
- assert_queries(1) do
17
- assert_equal [], Item.fetch_by_title_and_id('garbage', 'garbage')
18
- end
19
- end
20
-
21
- def test_fetch_with_unique_adds_limit_clause
22
- Item.cache_index :title, :id, :unique => true
23
-
24
- Item.connection.expects(:exec_query)
25
- .with(regexp_matches(/ LIMIT 1\Z/i), any_parameters)
26
- .returns(ActiveRecord::Result.new([], []))
27
-
28
- assert_nil Item.fetch_by_title_and_id('title', '2')
29
- end
30
-
31
- def test_unique_index_caches_nil
32
- Item.cache_index :title, :unique => true
33
- assert_nil Item.fetch_by_title('bob')
34
- assert_equal IdentityCache::CACHED_NIL, backend.read(cache_key(unique: true))
35
- end
36
-
37
- def test_unique_index_expired_by_new_record
38
- Item.cache_index :title, :unique => true
39
- IdentityCache.cache.write(cache_key(unique: true), IdentityCache::CACHED_NIL)
40
- @record.save!
41
- assert_equal IdentityCache::DELETED, backend.read(cache_key(unique: true))
42
- end
43
-
44
- def test_unique_index_filled_on_fetch_by
45
- Item.cache_index :title, :unique => true
46
- @record.save!
47
- assert_equal @record, Item.fetch_by_title('bob')
48
- assert_equal @record.id, backend.read(cache_key(unique: true))
49
- end
50
-
51
- def test_unique_index_expired_by_updated_record
52
- Item.cache_index :title, :unique => true
53
- @record.save!
54
- old_cache_key = cache_key(unique: true)
55
- IdentityCache.cache.write(old_cache_key, @record.id)
56
-
57
- @record.title = 'robert'
58
- new_cache_key = cache_key(unique: true)
59
- IdentityCache.cache.write(new_cache_key, IdentityCache::CACHED_NIL)
60
- @record.save!
61
- assert_equal IdentityCache::DELETED, backend.read(old_cache_key)
62
- assert_equal IdentityCache::DELETED, backend.read(new_cache_key)
63
- end
64
-
65
- def test_non_unique_index_caches_empty_result
66
- Item.cache_index :title
67
- assert_equal [], Item.fetch_by_title('bob')
68
- assert_equal [], backend.read(cache_key)
69
- end
70
-
71
- def test_non_unique_index_expired_by_new_record
72
- Item.cache_index :title
73
- IdentityCache.cache.write(cache_key, [])
74
- @record.save!
75
- assert_equal IdentityCache::DELETED, backend.read(cache_key)
76
- end
77
-
78
- def test_non_unique_index_filled_on_fetch_by
79
- Item.cache_index :title
80
- @record.save!
81
- assert_equal [@record], Item.fetch_by_title('bob')
82
- assert_equal [@record.id], backend.read(cache_key)
83
- end
84
-
85
- def test_non_unique_index_fetches_multiple_records
86
- Item.cache_index :title
87
- @record.save!
88
- record2 = Item.create(:title => 'bob') { |item| item.id = 2 }
89
-
90
- assert_equal [@record, record2], Item.fetch_by_title('bob')
91
- assert_equal [1, 2], backend.read(cache_key)
92
- end
93
-
94
- def test_non_unique_index_expired_by_updating_record
95
- Item.cache_index :title
96
- @record.save!
97
- old_cache_key = cache_key
98
- IdentityCache.cache.write(old_cache_key, [@record.id])
99
-
100
- @record.title = 'robert'
101
- new_cache_key = cache_key
102
- IdentityCache.cache.write(new_cache_key, [])
103
- @record.save!
104
- assert_equal IdentityCache::DELETED, backend.read(old_cache_key)
105
- assert_equal IdentityCache::DELETED, backend.read(new_cache_key)
106
- end
107
-
108
- def test_non_unique_index_expired_by_destroying_record
109
- Item.cache_index :title
110
- @record.save!
111
- IdentityCache.cache.write(cache_key, [@record.id])
112
- @record.destroy
113
- assert_equal IdentityCache::DELETED, backend.read(cache_key)
114
- end
115
-
116
- def test_set_table_name_cache_fetch
117
- Item.cache_index :title
118
- Item.table_name = 'items2'
119
- @record.save!
120
- assert_equal [@record], Item.fetch_by_title('bob')
121
- assert_equal [@record.id], backend.read(cache_key)
122
- end
123
-
124
- def test_fetch_by_index_raises_when_called_on_a_scope
125
- Item.cache_index :title
126
- assert_raises(IdentityCache::UnsupportedScopeError) do
127
- Item.where(updated_at: nil).fetch_by_title('bob')
128
- end
129
- end
130
-
131
- def test_fetch_by_unique_index_raises_when_called_on_a_scope
132
- Item.cache_index :title, :id, :unique => true
133
- assert_raises(IdentityCache::UnsupportedScopeError) do
134
- Item.where(updated_at: nil).fetch_by_title_and_id('bob', 2)
135
- end
136
- end
137
-
138
- def test_cache_index_on_derived_model_raises
139
- assert_raises(IdentityCache::DerivedModelError) do
140
- StiRecordTypeA.cache_index :name, :id
141
- end
142
- end
143
-
144
- def test_cache_index_with_non_id_primary_key
145
- KeyedRecord.cache_index :value
146
- KeyedRecord.create!(value: "a") { |r| r.hashed_key = 123 }
147
- assert_equal [123], KeyedRecord.fetch_by_value('a').map(&:id)
148
- end
149
-
150
- def test_unique_cache_index_with_non_id_primary_key
151
- KeyedRecord.cache_index :value, unique: true
152
- KeyedRecord.create!(value: "a") { |r| r.hashed_key = 123 }
153
- assert_equal 123, KeyedRecord.fetch_by_value('a').id
154
- end
155
-
156
- private
157
-
158
- def cache_key(unique: false)
159
- "#{NAMESPACE}attr#{unique ? '' : 's'}:Item:id:title:#{cache_hash(@record.title)}"
160
- end
161
- end
@@ -1,59 +0,0 @@
1
- require "test_helper"
2
-
3
- class MemoizedAttributesTest < IdentityCache::TestCase
4
- def setup
5
- IdentityCache.fetch_read_only_records = false
6
- super
7
- end
8
-
9
- def teardown
10
- super
11
- IdentityCache.fetch_read_only_records = true
12
- end
13
-
14
- def test_memoization_should_not_break_dirty_tracking_with_empty_cache
15
- item = Item.create!
16
-
17
- IdentityCache.cache.with_memoization do
18
- Item.fetch(item.id).title = "my title"
19
- Item.fetch(item.id).update!(title: "my title")
20
- end
21
-
22
- assert_equal "my title", Item.find(item.id).title
23
- end
24
-
25
- def test_memoization_should_not_break_dirty_tracking_with_filled_cache
26
- item = Item.create!
27
-
28
- IdentityCache.cache.with_memoization do
29
- Item.fetch(item.id)
30
- Item.fetch(item.id).title = "my title"
31
- Item.fetch(item.id).update!(title: "my title")
32
- end
33
-
34
- assert_equal "my title", Item.find(item.id).title
35
- end
36
-
37
- def test_memoization_with_fetch_multi_should_not_break_dirty_tracking_with_empty_cache
38
- item = Item.create!
39
-
40
- IdentityCache.cache.with_memoization do
41
- Item.fetch_multi(item.id).first.title = "my title"
42
- Item.fetch_multi(item.id).first.update!(title: "my title")
43
- end
44
-
45
- assert_equal "my title", Item.find(item.id).title
46
- end
47
-
48
- def test_memoization_with_fetch_multi_should_not_break_dirty_tracking_with_filled_cache
49
- item = Item.create!
50
-
51
- IdentityCache.cache.with_memoization do
52
- Item.fetch_multi(item.id)
53
- Item.fetch_multi(item.id).first.title = "my title"
54
- Item.fetch_multi(item.id).first.update!(title: "my title")
55
- end
56
-
57
- assert_equal "my title", Item.find(item.id).title
58
- end
59
- end
@@ -1,107 +0,0 @@
1
- require "test_helper"
2
-
3
- class MemoizedCacheProxyTest < IdentityCache::TestCase
4
- def test_changing_default_cache
5
- IdentityCache.cache_backend = ActiveSupport::Cache::MemoryStore.new
6
- IdentityCache.cache.write('foo', 'bar')
7
- assert_equal 'bar', IdentityCache.cache.fetch('foo')
8
- end
9
-
10
- def test_fetch_multi_with_fallback_fetcher
11
- IdentityCache.cache_backend = backend = ActiveSupport::Cache::MemoryStore.new
12
- IdentityCache.cache.write('foo', 'bar')
13
- backend.expects(:write).with('bar', 'baz')
14
- yielded = nil
15
- assert_equal({'foo' => 'bar', 'bar' => 'baz'}, IdentityCache.cache.fetch_multi('foo', 'bar') {|_| yielded = ['baz'] })
16
- assert_equal ['baz'], yielded
17
- end
18
-
19
- def test_fetch_should_short_circuit_on_memoized_values
20
- fetcher.expects(:fetch).never
21
-
22
- IdentityCache.cache.with_memoization do
23
- IdentityCache.cache.write('foo', 'bar')
24
- assert_equal 'bar', IdentityCache.cache.fetch('foo')
25
- end
26
- end
27
-
28
- def test_fetch_should_short_circuit_on_falsy_memoized_values
29
- fetcher.expects(:fetch).never
30
-
31
- IdentityCache.cache.with_memoization do
32
- IdentityCache.cache.write('foo', nil)
33
- assert_nil IdentityCache.cache.fetch('foo')
34
- IdentityCache.cache.write('bar', false)
35
- assert_equal false, IdentityCache.cache.fetch('bar')
36
- end
37
- end
38
-
39
- def test_fetch_should_try_memcached_on_not_memoized_values
40
- fetcher.expects(:fetch).with('foo').returns('bar')
41
-
42
- IdentityCache.cache.with_memoization do
43
- assert_equal 'bar', IdentityCache.cache.fetch('foo')
44
- end
45
- end
46
-
47
- def test_write_should_memoize_values
48
- fetcher.expects(:fetch).never
49
- fetcher.expects(:write).with('foo', 'bar')
50
-
51
- IdentityCache.cache.with_memoization do
52
- IdentityCache.cache.write('foo', 'bar')
53
- assert_equal 'bar', IdentityCache.cache.fetch('foo')
54
- end
55
- end
56
-
57
- def test_fetch_should_memoize_values
58
- backend.write('foo', 'bar')
59
-
60
- IdentityCache.cache.with_memoization do
61
- assert_equal 'bar', IdentityCache.cache.fetch('foo')
62
- backend.delete('foo')
63
- assert_equal 'bar', IdentityCache.cache.fetch('foo')
64
- end
65
- end
66
-
67
- def test_fetch_multi_should_memoize_values
68
- expected_hash = {'foo' => 'bar', 'fooz' => IdentityCache::CACHED_NIL}
69
-
70
- backend.write('foo', 'bar')
71
-
72
- IdentityCache.cache.with_memoization do
73
- assert_equal(expected_hash, IdentityCache.cache.fetch_multi('foo', 'fooz') {|_| [IdentityCache::CACHED_NIL] })
74
- assert_equal(expected_hash, IdentityCache.cache.memoized_key_values)
75
- backend.delete('foo')
76
- backend.write('fooz', 'baz')
77
- assert_equal(expected_hash, IdentityCache.cache.fetch_multi('foo', 'fooz'))
78
- end
79
- end
80
-
81
- def test_fetch_multi_with_partially_memoized_should_read_missing_keys_from_memcache
82
- IdentityCache.cache.write('foo', 'bar')
83
- @backend.write('fooz', 'baz')
84
-
85
- IdentityCache.cache.with_memoization do
86
- assert_equal({'foo' => 'bar', 'fooz' => 'baz'}, IdentityCache.cache.fetch_multi('foo', 'fooz'))
87
- end
88
- end
89
-
90
- def test_fetch_multi_with_blank_values_should_not_hit_the_cache_engine
91
- @backend.expects(:fetch_multi).never
92
-
93
- IdentityCache.cache.with_memoization do
94
- IdentityCache.cache.write('foo', [])
95
- IdentityCache.cache.write('bar', false)
96
- IdentityCache.cache.write('baz', {})
97
- assert_equal({'foo' => [], 'bar' => false, 'baz' => {}}, IdentityCache.cache.fetch_multi('foo', 'bar', 'baz'))
98
- end
99
- end
100
-
101
- def test_with_memoization_should_not_clear_rails_cache_when_the_block_ends
102
- IdentityCache.cache.with_memoization do
103
- IdentityCache.cache.write('foo', 'bar')
104
- end
105
- assert_equal 'bar', @backend.fetch('foo')
106
- end
107
- end
@@ -1,107 +0,0 @@
1
- require "test_helper"
2
-
3
- class NormalizedBelongsToTest < IdentityCache::TestCase
4
- def setup
5
- super
6
- AssociatedRecord.cache_belongs_to :item, :embed => false
7
-
8
- @parent_record = Item.new(:title => 'foo')
9
- @parent_record.associated_records << AssociatedRecord.new(:name => 'bar')
10
- @parent_record.save
11
- @parent_record.reload
12
- @record = @parent_record.associated_records.first
13
- # Reset association cache, so we remove the inverse of in memory reference
14
- @record.association(:item).reset
15
- end
16
-
17
- def test_fetching_the_association_should_delegate_to_the_normal_association_fetcher_if_any_transactions_are_open
18
- Item.expects(:fetch_by_id).never
19
- @record.transaction do
20
- assert_equal @parent_record, @record.fetch_item
21
- end
22
- end
23
-
24
- def test_fetching_the_association_should_delegate_to_the_normal_association_fetcher_if_the_normal_association_is_loaded
25
- # Warm the ActiveRecord association
26
- @record.item
27
-
28
- Item.expects(:fetch_by_id).never
29
- assert_equal @parent_record, @record.fetch_item
30
- end
31
-
32
- def test_fetching_the_association_should_fetch_the_record_from_identity_cache
33
- Item.expects(:fetch_by_id).with(@parent_record.id).returns(@parent_record)
34
- assert_equal @parent_record, @record.fetch_item
35
- end
36
-
37
- def test_fetching_the_association_should_assign_the_result_to_an_instance_variable_so_that_successive_accesses_are_cached
38
- Item.expects(:fetch_by_id).with(@parent_record.id).returns(@parent_record)
39
- assert_equal @parent_record, @record.fetch_item
40
- assert_equal false, @record.association(:item).loaded?
41
- assert_equal @parent_record, @record.fetch_item
42
- end
43
-
44
- def test_fetching_the_association_should_cache_nil_and_not_raise_if_the_record_cant_be_found
45
- Item.expects(:fetch_by_id).with(@parent_record.id).returns(nil)
46
- assert_nil @record.fetch_item # miss
47
- assert_nil @record.fetch_item # hit
48
- end
49
-
50
- def test_cache_belongs_to_on_derived_model_raises
51
- assert_raises(IdentityCache::DerivedModelError) do
52
- StiRecordTypeA.cache_belongs_to :item, :embed => false
53
- end
54
- end
55
-
56
- def test_fetching_polymorphic_belongs_to_association
57
- PolymorphicRecord.include IdentityCache
58
- PolymorphicRecord.cache_belongs_to :owner
59
- PolymorphicRecord.create!(owner: @parent_record)
60
-
61
- assert_equal @parent_record, PolymorphicRecord.first.fetch_owner
62
- end
63
-
64
- def test_returned_record_should_be_readonly_on_cache_hit
65
- IdentityCache.with_fetch_read_only_records do
66
- @record.fetch_item # warm cache
67
- assert @record.fetch_item.readonly?
68
- refute @record.item.readonly?
69
- end
70
- end
71
-
72
- def test_returned_record_should_be_readonly_on_cache_miss
73
- IdentityCache.with_fetch_read_only_records do
74
- assert @record.fetch_item.readonly?
75
- refute @record.item.readonly?
76
- end
77
- end
78
-
79
- def test_db_returned_record_should_never_be_readonly
80
- IdentityCache.with_fetch_read_only_records do
81
- uncached_record = @record.item
82
- refute uncached_record.readonly?
83
- @record.fetch_item
84
- refute uncached_record.readonly?
85
- end
86
- end
87
-
88
- def test_returned_record_with_open_transactions_should_not_be_readonly
89
- IdentityCache.with_fetch_read_only_records do
90
- Item.transaction do
91
- refute IdentityCache.should_use_cache?
92
- refute @record.fetch_item.readonly?
93
- end
94
- end
95
- end
96
-
97
- def test_respects_should_use_cache_on_parent
98
- @record.reload
99
- @parent_record.class.stubs(:should_use_cache?).returns(false)
100
-
101
- assert_queries(1) do
102
- assert_memcache_operations(0) do
103
- @record.fetch_item
104
- end
105
- end
106
- end
107
- end