identity_cache 0.5.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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