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.
- checksums.yaml +5 -5
- data/.github/probots.yml +2 -0
- data/.github/workflows/ci.yml +26 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +5 -0
- data/.travis.yml +24 -9
- data/CHANGELOG.md +21 -0
- data/Gemfile +5 -1
- data/README.md +28 -26
- data/Rakefile +14 -5
- data/dev.yml +9 -16
- data/gemfiles/Gemfile.latest-release +6 -0
- data/gemfiles/Gemfile.rails-edge +6 -0
- data/gemfiles/Gemfile.rails52 +6 -0
- data/identity_cache.gemspec +26 -10
- data/lib/identity_cache.rb +49 -46
- data/lib/identity_cache/belongs_to_caching.rb +12 -40
- data/lib/identity_cache/cache_fetcher.rb +6 -5
- data/lib/identity_cache/cache_hash.rb +2 -2
- data/lib/identity_cache/cache_invalidation.rb +4 -11
- data/lib/identity_cache/cache_key_generation.rb +17 -65
- data/lib/identity_cache/cache_key_loader.rb +128 -0
- data/lib/identity_cache/cached.rb +7 -0
- data/lib/identity_cache/cached/association.rb +87 -0
- data/lib/identity_cache/cached/attribute.rb +123 -0
- data/lib/identity_cache/cached/attribute_by_multi.rb +37 -0
- data/lib/identity_cache/cached/attribute_by_one.rb +88 -0
- data/lib/identity_cache/cached/belongs_to.rb +93 -0
- data/lib/identity_cache/cached/embedded_fetching.rb +41 -0
- data/lib/identity_cache/cached/prefetcher.rb +51 -0
- data/lib/identity_cache/cached/primary_index.rb +97 -0
- data/lib/identity_cache/cached/recursive/association.rb +68 -0
- data/lib/identity_cache/cached/recursive/has_many.rb +9 -0
- data/lib/identity_cache/cached/recursive/has_one.rb +9 -0
- data/lib/identity_cache/cached/reference/association.rb +16 -0
- data/lib/identity_cache/cached/reference/has_many.rb +105 -0
- data/lib/identity_cache/cached/reference/has_one.rb +100 -0
- data/lib/identity_cache/configuration_dsl.rb +53 -215
- data/lib/identity_cache/encoder.rb +95 -0
- data/lib/identity_cache/expiry_hook.rb +36 -0
- data/lib/identity_cache/fallback_fetcher.rb +2 -1
- data/lib/identity_cache/load_strategy/eager.rb +28 -0
- data/lib/identity_cache/load_strategy/lazy.rb +71 -0
- data/lib/identity_cache/load_strategy/load_request.rb +20 -0
- data/lib/identity_cache/load_strategy/multi_load_request.rb +27 -0
- data/lib/identity_cache/memoized_cache_proxy.rb +127 -58
- data/lib/identity_cache/parent_model_expiration.rb +45 -11
- data/lib/identity_cache/query_api.rb +128 -394
- data/lib/identity_cache/railtie.rb +8 -0
- data/lib/identity_cache/record_not_found.rb +6 -0
- data/lib/identity_cache/should_use_cache.rb +1 -0
- data/lib/identity_cache/version.rb +3 -2
- data/lib/identity_cache/with_primary_index.rb +136 -0
- data/lib/identity_cache/without_primary_index.rb +24 -3
- data/performance/cache_runner.rb +28 -34
- data/performance/cpu.rb +3 -2
- data/performance/externals.rb +4 -3
- data/performance/profile.rb +6 -5
- data/railgun.yml +16 -0
- metadata +44 -73
- data/Gemfile.rails42 +0 -6
- data/Gemfile.rails50 +0 -6
- data/test/attribute_cache_test.rb +0 -110
- data/test/cache_fetch_includes_test.rb +0 -46
- data/test/cache_hash_test.rb +0 -14
- data/test/cache_invalidation_test.rb +0 -139
- data/test/deeply_nested_associated_record_test.rb +0 -19
- data/test/denormalized_has_many_test.rb +0 -214
- data/test/denormalized_has_one_test.rb +0 -160
- data/test/fetch_multi_test.rb +0 -308
- data/test/fetch_test.rb +0 -258
- data/test/fixtures/serialized_record.mysql2 +0 -0
- data/test/fixtures/serialized_record.postgresql +0 -0
- data/test/helpers/active_record_objects.rb +0 -106
- data/test/helpers/database_connection.rb +0 -72
- data/test/helpers/serialization_format.rb +0 -51
- data/test/helpers/update_serialization_format.rb +0 -27
- data/test/identity_cache_test.rb +0 -29
- data/test/index_cache_test.rb +0 -161
- data/test/memoized_attributes_test.rb +0 -59
- data/test/memoized_cache_proxy_test.rb +0 -107
- data/test/normalized_belongs_to_test.rb +0 -107
- data/test/normalized_has_many_test.rb +0 -231
- data/test/normalized_has_one_test.rb +0 -9
- data/test/prefetch_associations_test.rb +0 -379
- data/test/readonly_test.rb +0 -109
- data/test/recursive_denormalized_has_many_test.rb +0 -131
- data/test/save_test.rb +0 -82
- data/test/schema_change_test.rb +0 -112
- data/test/serialization_format_change_test.rb +0 -16
- 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
|
data/test/identity_cache_test.rb
DELETED
@@ -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
|
data/test/index_cache_test.rb
DELETED
@@ -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
|