active_remote-cached 1.1.1 → 1.2.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 +4 -4
- data/.github/workflows/ci.yml +85 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +20 -17
- data/Appraisals +27 -0
- data/README.md +121 -0
- data/Rakefile +3 -8
- data/active_remote-cached.gemspec +31 -6
- data/lib/active_remote/cached/argument_keys.rb +61 -27
- data/lib/active_remote/cached/cache.rb +32 -6
- data/lib/active_remote/cached/version.rb +1 -1
- data/lib/active_remote/cached.rb +119 -68
- data/spec/active_remote/cached/argument_keys_spec.rb +124 -0
- data/spec/active_remote/cached/cache_spec.rb +171 -5
- data/spec/active_remote/cached_delete_methods_spec.rb +51 -4
- data/spec/active_remote/cached_exist_methods_spec.rb +75 -4
- data/spec/active_remote/cached_find_methods_spec.rb +6 -8
- data/spec/active_remote/cached_search_methods_spec.rb +57 -8
- data/spec/active_remote/cached_spec.rb +331 -0
- data/spec/spec_helper.rb +1 -0
- metadata +48 -23
|
@@ -3,30 +3,196 @@
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
|
|
5
5
|
describe ::ActiveRemote::Cached::Cache do
|
|
6
|
+
let(:invalid_provider_error) { ::ActiveRemote::Cached::Cache::InvalidCacheProvider }
|
|
7
|
+
let(:cache_provider) { ::ActiveSupport::Cache::MemoryStore.new }
|
|
8
|
+
let(:cache) { ::ActiveRemote::Cached::Cache.new(cache_provider) }
|
|
9
|
+
|
|
6
10
|
describe 'API' do
|
|
7
11
|
it 'validates #delete present' do
|
|
8
12
|
cache = OpenStruct.new(:write => nil, :fetch => nil, :read => nil, :exist? => nil)
|
|
9
|
-
expect { ::ActiveRemote::Cached.cache(cache) }.to raise_error(
|
|
13
|
+
expect { ::ActiveRemote::Cached.cache(cache) }.to raise_error(invalid_provider_error, /respond_to.*delete/i)
|
|
10
14
|
end
|
|
11
15
|
|
|
12
16
|
it 'validates #exist? present' do
|
|
13
17
|
cache = OpenStruct.new(:write => nil, :delete => nil, :read => nil, :fetch => nil)
|
|
14
|
-
expect { ::ActiveRemote::Cached.cache(cache) }.to raise_error(
|
|
18
|
+
expect { ::ActiveRemote::Cached.cache(cache) }.to raise_error(invalid_provider_error, /respond_to.*exist/i)
|
|
15
19
|
end
|
|
16
20
|
|
|
17
21
|
it 'validates #fetch present' do
|
|
18
22
|
cache = OpenStruct.new(:write => nil, :delete => nil, :read => nil, :exist? => nil)
|
|
19
|
-
expect { ::ActiveRemote::Cached.cache(cache) }.to raise_error(
|
|
23
|
+
expect { ::ActiveRemote::Cached.cache(cache) }.to raise_error(invalid_provider_error, /respond_to.*fetch/i)
|
|
20
24
|
end
|
|
21
25
|
|
|
22
26
|
it 'validates #read present' do
|
|
23
27
|
cache = OpenStruct.new(:write => nil, :delete => nil, :fetch => nil, :exist? => nil)
|
|
24
|
-
expect { ::ActiveRemote::Cached.cache(cache) }.to raise_error(
|
|
28
|
+
expect { ::ActiveRemote::Cached.cache(cache) }.to raise_error(invalid_provider_error, /respond_to.*read/i)
|
|
25
29
|
end
|
|
26
30
|
|
|
27
31
|
it 'validates #write present' do
|
|
28
32
|
cache = OpenStruct.new(:read => nil, :delete => nil, :fetch => nil, :exist? => nil)
|
|
29
|
-
expect { ::ActiveRemote::Cached.cache(cache) }.to raise_error(
|
|
33
|
+
expect { ::ActiveRemote::Cached.cache(cache) }.to raise_error(invalid_provider_error, /respond_to.*write/i)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe '#nested_caching?' do
|
|
38
|
+
it 'is false before nested caching is enabled' do
|
|
39
|
+
expect(cache.nested_caching?).to eq(false)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe 'delegation' do
|
|
44
|
+
it 'exposes the cache provider it was given' do
|
|
45
|
+
expect(cache.cache_provider).to be(cache_provider)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'delegates unknown methods to the cache provider' do
|
|
49
|
+
expect(cache_provider).to receive(:clear).and_return(:cleared)
|
|
50
|
+
expect(cache.clear).to eq(:cleared)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
describe '#fetch' do
|
|
55
|
+
it 'returns a nil value but does not persist it by default' do
|
|
56
|
+
expect(cache.fetch('key') { nil }).to be_nil
|
|
57
|
+
expect(cache_provider.exist?('key')).to eq(false)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'returns an empty value but does not persist it by default' do
|
|
61
|
+
expect(cache.fetch('key') { [] }).to eq([])
|
|
62
|
+
expect(cache_provider.exist?('key')).to eq(false)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'persists a nil value when :allow_nil is given' do
|
|
66
|
+
expect(cache.fetch('key', :allow_nil => true) { nil }).to be_nil
|
|
67
|
+
expect(cache_provider.exist?('key')).to eq(true)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it 'persists an empty value when :allow_empty is given' do
|
|
71
|
+
expect(cache.fetch('key', :allow_empty => true) { [] }).to eq([])
|
|
72
|
+
expect(cache_provider.exist?('key')).to eq(true)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'persists a value that is neither nil nor empty' do
|
|
76
|
+
expect(cache.fetch('key') { [:record] }).to eq([:record])
|
|
77
|
+
expect(cache_provider.exist?('key')).to eq(true)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
describe '#fetch round trips' do
|
|
82
|
+
let(:counting_provider) do
|
|
83
|
+
Class.new(::ActiveSupport::Cache::MemoryStore) do
|
|
84
|
+
def initialize(*args)
|
|
85
|
+
@calls = []
|
|
86
|
+
super
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
attr_reader :calls
|
|
90
|
+
|
|
91
|
+
def fetch(*args, **options, &block)
|
|
92
|
+
@calls << :fetch
|
|
93
|
+
super
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def write(*args, **options)
|
|
97
|
+
@calls << :write
|
|
98
|
+
super
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def delete(*args, **options)
|
|
102
|
+
@calls << :delete
|
|
103
|
+
super
|
|
104
|
+
end
|
|
105
|
+
end.new
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# The provider used to write the nil and then take a second round trip to
|
|
109
|
+
# delete it. :skip_nil makes the provider skip the write.
|
|
110
|
+
it 'takes one provider call for a nil value' do
|
|
111
|
+
cache = ::ActiveRemote::Cached::Cache.new(counting_provider)
|
|
112
|
+
|
|
113
|
+
cache.fetch('key') { nil }
|
|
114
|
+
|
|
115
|
+
expect(counting_provider.calls).to eq([:fetch])
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'still writes a nil when :allow_nil is given' do
|
|
119
|
+
cache = ::ActiveRemote::Cached::Cache.new(counting_provider)
|
|
120
|
+
|
|
121
|
+
cache.fetch('key', :allow_nil => true) { nil }
|
|
122
|
+
|
|
123
|
+
expect(counting_provider.calls).to eq(%i[fetch write])
|
|
124
|
+
expect(counting_provider.exist?('key')).to eq(true)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
describe '#enable_nested_caching!' do
|
|
129
|
+
it 'writes to the cache provider only until nested caching is enabled' do
|
|
130
|
+
cache.write('key', 'value')
|
|
131
|
+
|
|
132
|
+
expect(cache_provider.read('key')).to eq('value')
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
context 'when nested caching is enabled' do
|
|
136
|
+
before do
|
|
137
|
+
cache.enable_nested_caching!
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it 'writes to both the nested cache and the cache provider' do
|
|
141
|
+
cache.write('key', 'value')
|
|
142
|
+
|
|
143
|
+
expect(cache.read('key')).to eq('value')
|
|
144
|
+
expect(cache_provider.read('key')).to eq('value')
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it 'deletes from both the nested cache and the cache provider' do
|
|
148
|
+
cache.write('key', 'value')
|
|
149
|
+
cache.delete('key')
|
|
150
|
+
|
|
151
|
+
expect(cache.read('key')).to be_nil
|
|
152
|
+
expect(cache_provider.read('key')).to be_nil
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it 'reads the nested value in preference to the cache provider value' do
|
|
156
|
+
cache.write('key', 'nested')
|
|
157
|
+
cache_provider.write('key', 'provider')
|
|
158
|
+
|
|
159
|
+
expect(cache.read('key')).to eq('nested')
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it 'reports a key that only the cache provider holds' do
|
|
163
|
+
cache_provider.write('key', 'provider')
|
|
164
|
+
|
|
165
|
+
expect(cache.exist?('key')).to eq(true)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it 'reports that nested caching is on' do
|
|
169
|
+
expect(cache.nested_caching?).to eq(true)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# A new Cache starts with nested caching off, so swapping the provider
|
|
173
|
+
# used to turn the setting off without saying so.
|
|
174
|
+
it 'keeps nested caching on when the cache provider is replaced' do
|
|
175
|
+
original_cache = ::ActiveRemote::Cached.cache
|
|
176
|
+
|
|
177
|
+
::ActiveRemote::Cached.cache(cache_provider)
|
|
178
|
+
::ActiveRemote::Cached.cache.enable_nested_caching!
|
|
179
|
+
::ActiveRemote::Cached.cache(::ActiveSupport::Cache::MemoryStore.new)
|
|
180
|
+
|
|
181
|
+
expect(::ActiveRemote::Cached.cache.nested_caching?).to eq(true)
|
|
182
|
+
ensure
|
|
183
|
+
# .cache now carries the nested setting forward, so reset the module
|
|
184
|
+
# rather than call it again.
|
|
185
|
+
::ActiveRemote::Cached.instance_variable_set(:@cache_provider, original_cache)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# #read joins the two providers with ||, so a false value in the nested
|
|
189
|
+
# cache falls through to the cache provider. This records that behavior.
|
|
190
|
+
it 'falls through to the cache provider when the nested value is false' do
|
|
191
|
+
cache.write('key', false)
|
|
192
|
+
cache_provider.write('key', 'provider')
|
|
193
|
+
|
|
194
|
+
expect(cache.read('key')).to eq('provider')
|
|
195
|
+
end
|
|
30
196
|
end
|
|
31
197
|
end
|
|
32
198
|
end
|
|
@@ -5,12 +5,12 @@ require 'spec_helper'
|
|
|
5
5
|
class DeleteMethodClass
|
|
6
6
|
include ::ActiveRemote::Cached
|
|
7
7
|
|
|
8
|
-
def self.find
|
|
9
|
-
|
|
8
|
+
def self.find(*)
|
|
9
|
+
:record
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
def self.search
|
|
13
|
-
|
|
12
|
+
def self.search(*)
|
|
13
|
+
[:record]
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
cached_finders_for :guid
|
|
@@ -49,4 +49,51 @@ describe DeleteMethodClass do
|
|
|
49
49
|
expect(DeleteMethodClass).to respond_to(:cached_delete_by_client_guid_and_user_guid_and_derp)
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
|
+
|
|
53
|
+
describe '#cached_delete_by_guid' do
|
|
54
|
+
before do
|
|
55
|
+
::ActiveRemote::Cached.cache(HashCache.new)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
after do
|
|
59
|
+
::ActiveRemote::Cached.default_options({})
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'deletes the find cache key' do
|
|
63
|
+
DeleteMethodClass.cached_find_by_guid(:guid)
|
|
64
|
+
expect(DeleteMethodClass.cached_exist_find_by_guid?(:guid)).to eq(true)
|
|
65
|
+
|
|
66
|
+
DeleteMethodClass.cached_delete_by_guid(:guid)
|
|
67
|
+
|
|
68
|
+
expect(DeleteMethodClass.cached_exist_find_by_guid?(:guid)).to eq(false)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'deletes the search cache key' do
|
|
72
|
+
DeleteMethodClass.cached_search_by_guid(:guid)
|
|
73
|
+
expect(DeleteMethodClass.cached_exist_search_by_guid?(:guid)).to eq(true)
|
|
74
|
+
|
|
75
|
+
DeleteMethodClass.cached_delete_by_guid(:guid)
|
|
76
|
+
|
|
77
|
+
expect(DeleteMethodClass.cached_exist_search_by_guid?(:guid)).to eq(false)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'does not raise when the cache keys are not present' do
|
|
81
|
+
expect { DeleteMethodClass.cached_delete_by_guid(:missing) }.not_to raise_error
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
describe 'namespaced cache' do
|
|
85
|
+
it 'deletes the namespaced find and search cache keys' do
|
|
86
|
+
expect(::ActiveRemote::Cached.cache).to receive(:delete).with(
|
|
87
|
+
[::ActiveRemote::Cached::RUBY_AND_ACTIVE_SUPPORT_VERSION, 'MyApp', DeleteMethodClass.name, '#find',
|
|
88
|
+
'guid.guid']
|
|
89
|
+
)
|
|
90
|
+
expect(::ActiveRemote::Cached.cache).to receive(:delete).with(
|
|
91
|
+
[::ActiveRemote::Cached::RUBY_AND_ACTIVE_SUPPORT_VERSION, 'MyApp', DeleteMethodClass.name, '#search',
|
|
92
|
+
'guid.guid']
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
DeleteMethodClass.cached_delete_by_guid(:guid, :namespace => 'MyApp')
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
52
99
|
end
|
|
@@ -5,12 +5,12 @@ require 'spec_helper'
|
|
|
5
5
|
class ExistMethodClass
|
|
6
6
|
include ::ActiveRemote::Cached
|
|
7
7
|
|
|
8
|
-
def self.find
|
|
9
|
-
|
|
8
|
+
def self.find(*)
|
|
9
|
+
:record
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
def self.search
|
|
13
|
-
|
|
12
|
+
def self.search(*)
|
|
13
|
+
[:record]
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
cached_finders_for :guid
|
|
@@ -134,4 +134,75 @@ describe ExistMethodClass do
|
|
|
134
134
|
expect(ExistMethodClass).to respond_to(:cached_exist_search_by_client_guid_and_user_guid_and_derp?)
|
|
135
135
|
end
|
|
136
136
|
end
|
|
137
|
+
|
|
138
|
+
describe '#cached_exist_find_by_guid?' do
|
|
139
|
+
before do
|
|
140
|
+
::ActiveRemote::Cached.cache(HashCache.new)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
after do
|
|
144
|
+
::ActiveRemote::Cached.default_options({})
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it 'returns false before the find cache key is written' do
|
|
148
|
+
expect(ExistMethodClass.cached_exist_find_by_guid?(:guid)).to eq(false)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it 'returns true after the find cache key is written' do
|
|
152
|
+
ExistMethodClass.cached_find_by_guid(:guid)
|
|
153
|
+
|
|
154
|
+
expect(ExistMethodClass.cached_exist_find_by_guid?(:guid)).to eq(true)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it 'returns the same result as the method without the question mark' do
|
|
158
|
+
ExistMethodClass.cached_find_by_guid(:guid)
|
|
159
|
+
|
|
160
|
+
expect(ExistMethodClass.cached_exist_find_by_guid(:guid)).to eq(
|
|
161
|
+
ExistMethodClass.cached_exist_find_by_guid?(:guid)
|
|
162
|
+
)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it 'ignores a search cache key for the same arguments' do
|
|
166
|
+
ExistMethodClass.cached_search_by_guid(:guid)
|
|
167
|
+
|
|
168
|
+
expect(ExistMethodClass.cached_exist_find_by_guid?(:guid)).to eq(false)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
describe 'namespaced cache' do
|
|
172
|
+
it 'uses the namespace as a prefix to the cache key' do
|
|
173
|
+
expect(::ActiveRemote::Cached.cache).to receive(:exist?).with(
|
|
174
|
+
[::ActiveRemote::Cached::RUBY_AND_ACTIVE_SUPPORT_VERSION, 'MyApp', ExistMethodClass.name, '#find',
|
|
175
|
+
'guid.guid']
|
|
176
|
+
).and_return(true)
|
|
177
|
+
|
|
178
|
+
expect(ExistMethodClass.cached_exist_find_by_guid?(:guid, :namespace => 'MyApp')).to eq(true)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
describe '#cached_exist_search_by_guid?' do
|
|
184
|
+
before do
|
|
185
|
+
::ActiveRemote::Cached.cache(HashCache.new)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
after do
|
|
189
|
+
::ActiveRemote::Cached.default_options({})
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it 'returns false before the search cache key is written' do
|
|
193
|
+
expect(ExistMethodClass.cached_exist_search_by_guid?(:guid)).to eq(false)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it 'returns true after the search cache key is written' do
|
|
197
|
+
ExistMethodClass.cached_search_by_guid(:guid)
|
|
198
|
+
|
|
199
|
+
expect(ExistMethodClass.cached_exist_search_by_guid?(:guid)).to eq(true)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
it 'ignores a find cache key for the same arguments' do
|
|
203
|
+
ExistMethodClass.cached_find_by_guid(:guid)
|
|
204
|
+
|
|
205
|
+
expect(ExistMethodClass.cached_exist_search_by_guid?(:guid)).to eq(false)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
137
208
|
end
|
|
@@ -21,9 +21,7 @@ class FindMethodClass
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
describe FindMethodClass do
|
|
24
|
-
let(:versioned_prefix)
|
|
25
|
-
"#{RUBY_ENGINE_VERSION}:#{ActiveSupport::VERSION::STRING}"
|
|
26
|
-
end
|
|
24
|
+
let(:versioned_prefix) { ::ActiveRemote::Cached::RUBY_AND_ACTIVE_SUPPORT_VERSION }
|
|
27
25
|
|
|
28
26
|
describe 'API' do
|
|
29
27
|
it "creates 'cached_find_by_foo'" do
|
|
@@ -81,7 +79,7 @@ describe FindMethodClass do
|
|
|
81
79
|
|
|
82
80
|
it 'merges the default options in for the fetch call' do
|
|
83
81
|
expect(::ActiveRemote::Cached.cache).to receive(:fetch).with(
|
|
84
|
-
[versioned_prefix, FindMethodClass.name, '#find', 'guid'], { :expires_in => 100 }
|
|
82
|
+
[versioned_prefix, FindMethodClass.name, '#find', 'guid.guid'], { :expires_in => 100 }
|
|
85
83
|
).and_return(:hello)
|
|
86
84
|
expect(FindMethodClass).not_to receive(:find)
|
|
87
85
|
expect(FindMethodClass.cached_find_by_guid(:guid)).to eq(:hello)
|
|
@@ -89,7 +87,7 @@ describe FindMethodClass do
|
|
|
89
87
|
|
|
90
88
|
it 'overrides the default options with local options for the fetch call' do
|
|
91
89
|
expect(::ActiveRemote::Cached.cache).to receive(:fetch).with(
|
|
92
|
-
[versioned_prefix, FindMethodClass.name, '#find', 'guid'], { :expires_in => 200 }
|
|
90
|
+
[versioned_prefix, FindMethodClass.name, '#find', 'guid.guid'], { :expires_in => 200 }
|
|
93
91
|
).and_return(:hello)
|
|
94
92
|
expect(FindMethodClass).not_to receive(:find)
|
|
95
93
|
|
|
@@ -103,7 +101,7 @@ describe FindMethodClass do
|
|
|
103
101
|
|
|
104
102
|
it 'uses the namespace as a prefix to the cache key' do
|
|
105
103
|
expect(::ActiveRemote::Cached.cache).to receive(:fetch).with(
|
|
106
|
-
[versioned_prefix, 'MyApp', FindMethodClass.name, '#find', 'guid'], { :expires_in => 100 }
|
|
104
|
+
[versioned_prefix, 'MyApp', FindMethodClass.name, '#find', 'guid.guid'], { :expires_in => 100 }
|
|
107
105
|
).and_return(:hello)
|
|
108
106
|
|
|
109
107
|
expect(FindMethodClass).not_to receive(:find)
|
|
@@ -124,7 +122,7 @@ describe FindMethodClass do
|
|
|
124
122
|
|
|
125
123
|
it 'overrides the default options with cached_finder options for the fetch call' do
|
|
126
124
|
expect(::ActiveRemote::Cached.cache).to receive(:fetch).with(
|
|
127
|
-
[versioned_prefix, FindMethodClass.name, '#find', 'foo'], { :expires_in => 500 }
|
|
125
|
+
[versioned_prefix, FindMethodClass.name, '#find', 'foo.foo'], { :expires_in => 500 }
|
|
128
126
|
).and_return(:hello)
|
|
129
127
|
|
|
130
128
|
expect(FindMethodClass).not_to receive(:find)
|
|
@@ -133,7 +131,7 @@ describe FindMethodClass do
|
|
|
133
131
|
|
|
134
132
|
it 'overrides the cached_finder options with local options for the fetch call' do
|
|
135
133
|
expect(::ActiveRemote::Cached.cache).to receive(:fetch).with(
|
|
136
|
-
[versioned_prefix, FindMethodClass.name, '#find', 'foo'], { :expires_in => 200 }
|
|
134
|
+
[versioned_prefix, FindMethodClass.name, '#find', 'foo.foo'], { :expires_in => 200 }
|
|
137
135
|
).and_return(:hello)
|
|
138
136
|
|
|
139
137
|
expect(FindMethodClass).not_to receive(:find)
|
|
@@ -26,9 +26,7 @@ class SearchMethodClass
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
describe SearchMethodClass do
|
|
29
|
-
let(:versioned_prefix)
|
|
30
|
-
"#{RUBY_ENGINE_VERSION}:#{ActiveSupport::VERSION::STRING}"
|
|
31
|
-
end
|
|
29
|
+
let(:versioned_prefix) { ::ActiveRemote::Cached::RUBY_AND_ACTIVE_SUPPORT_VERSION }
|
|
32
30
|
|
|
33
31
|
describe 'API' do
|
|
34
32
|
it "creates 'cached_search_by_foo'" do
|
|
@@ -166,7 +164,7 @@ describe SearchMethodClass do
|
|
|
166
164
|
|
|
167
165
|
it 'merges the default options in for the fetch call' do
|
|
168
166
|
expect(::ActiveRemote::Cached.cache).to receive(:fetch).with(
|
|
169
|
-
[versioned_prefix, SearchMethodClass.name, '#search', 'guid'], { :expires_in => 100 }
|
|
167
|
+
[versioned_prefix, SearchMethodClass.name, '#search', 'guid.guid'], { :expires_in => 100 }
|
|
170
168
|
).and_return(:hello)
|
|
171
169
|
|
|
172
170
|
expect(SearchMethodClass).not_to receive(:search)
|
|
@@ -175,7 +173,7 @@ describe SearchMethodClass do
|
|
|
175
173
|
|
|
176
174
|
it 'overrides the default options with local options for the fetch call' do
|
|
177
175
|
expect(::ActiveRemote::Cached.cache).to receive(:fetch).with(
|
|
178
|
-
[versioned_prefix, SearchMethodClass.name, '#search', 'guid'], { :expires_in => 200 }
|
|
176
|
+
[versioned_prefix, SearchMethodClass.name, '#search', 'guid.guid'], { :expires_in => 200 }
|
|
179
177
|
).and_return(:hello)
|
|
180
178
|
|
|
181
179
|
expect(SearchMethodClass).not_to receive(:search)
|
|
@@ -189,7 +187,7 @@ describe SearchMethodClass do
|
|
|
189
187
|
|
|
190
188
|
it 'uses the namespace as a prefix to the cache key' do
|
|
191
189
|
expect(::ActiveRemote::Cached.cache).to receive(:fetch).with(
|
|
192
|
-
[versioned_prefix, 'MyApp', SearchMethodClass.name, '#search', 'guid'], { :expires_in => 100 }
|
|
190
|
+
[versioned_prefix, 'MyApp', SearchMethodClass.name, '#search', 'guid.guid'], { :expires_in => 100 }
|
|
193
191
|
).and_return(:hello)
|
|
194
192
|
|
|
195
193
|
expect(SearchMethodClass).not_to receive(:search)
|
|
@@ -210,7 +208,7 @@ describe SearchMethodClass do
|
|
|
210
208
|
|
|
211
209
|
it 'overrides the default options with cached_finder options for the fetch call' do
|
|
212
210
|
expect(::ActiveRemote::Cached.cache).to receive(:fetch).with(
|
|
213
|
-
[versioned_prefix, SearchMethodClass.name, '#search', 'foo'], { :expires_in => 500 }
|
|
211
|
+
[versioned_prefix, SearchMethodClass.name, '#search', 'foo.foo'], { :expires_in => 500 }
|
|
214
212
|
).and_return(:hello)
|
|
215
213
|
|
|
216
214
|
expect(SearchMethodClass).not_to receive(:find)
|
|
@@ -219,7 +217,7 @@ describe SearchMethodClass do
|
|
|
219
217
|
|
|
220
218
|
it 'overrides the cached_finder options with local options for the fetch call' do
|
|
221
219
|
expect(::ActiveRemote::Cached.cache).to receive(:fetch).with(
|
|
222
|
-
[versioned_prefix, SearchMethodClass.name, '#search', 'foo'], { :expires_in => 200 }
|
|
220
|
+
[versioned_prefix, SearchMethodClass.name, '#search', 'foo.foo'], { :expires_in => 200 }
|
|
223
221
|
).and_return(:hello)
|
|
224
222
|
|
|
225
223
|
expect(SearchMethodClass).not_to receive(:find)
|
|
@@ -248,6 +246,57 @@ describe SearchMethodClass do
|
|
|
248
246
|
SearchMethodClass.cached_search_by_foo!(:foo, :expires_in => 200)
|
|
249
247
|
end.to raise_error ::ActiveRemote::RemoteRecordNotFound
|
|
250
248
|
end
|
|
249
|
+
|
|
250
|
+
it 'raises ActiveRemote::RemoteRecordNotFound when the block returns no results' do
|
|
251
|
+
expect(SearchMethodClass).not_to receive(:search)
|
|
252
|
+
expect do
|
|
253
|
+
SearchMethodClass.cached_search_by_foo!(:foo) { [] }
|
|
254
|
+
end.to raise_error ::ActiveRemote::RemoteRecordNotFound
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
it 'raises ActiveRemote::RemoteRecordNotFound when the first result is nil' do
|
|
258
|
+
expect(SearchMethodClass).not_to receive(:search)
|
|
259
|
+
expect do
|
|
260
|
+
SearchMethodClass.cached_search_by_foo!(:foo) { [nil] }
|
|
261
|
+
end.to raise_error ::ActiveRemote::RemoteRecordNotFound
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
it 'raises ActiveRemote::RemoteRecordNotFound when the results are nil' do
|
|
265
|
+
expect(SearchMethodClass).to receive(:search).and_return(nil)
|
|
266
|
+
expect do
|
|
267
|
+
SearchMethodClass.cached_search_by_foo!(:foo)
|
|
268
|
+
end.to raise_error ::ActiveRemote::RemoteRecordNotFound
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
it 'names the model class in the error' do
|
|
272
|
+
expect(SearchMethodClass).to receive(:search).and_return([])
|
|
273
|
+
expect do
|
|
274
|
+
SearchMethodClass.cached_search_by_foo!(:foo)
|
|
275
|
+
end.to raise_error(::ActiveRemote::RemoteRecordNotFound, /SearchMethodClass/)
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
it 'reports the model class on the error' do
|
|
279
|
+
expect(SearchMethodClass).to receive(:search).and_return([])
|
|
280
|
+
|
|
281
|
+
SearchMethodClass.cached_search_by_foo!(:foo)
|
|
282
|
+
rescue ::ActiveRemote::RemoteRecordNotFound => e
|
|
283
|
+
expect(e.remote_record_class).to eq(SearchMethodClass)
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
it 'does not cache the results when it raises' do
|
|
287
|
+
expect do
|
|
288
|
+
SearchMethodClass.cached_search_by_foo!(:foo) { [] }
|
|
289
|
+
end.to raise_error ::ActiveRemote::RemoteRecordNotFound
|
|
290
|
+
|
|
291
|
+
expect(SearchMethodClass.cached_exist_search_by_foo?(:foo)).to eq(false)
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
it 'caches the results when they are present' do
|
|
295
|
+
expect(SearchMethodClass).to receive(:search).once.and_return([:hello])
|
|
296
|
+
|
|
297
|
+
expect(SearchMethodClass.cached_search_by_foo!(:foo)).to eq([:hello])
|
|
298
|
+
expect(SearchMethodClass.cached_search_by_foo!(:foo)).to eq([:hello])
|
|
299
|
+
end
|
|
251
300
|
end
|
|
252
301
|
|
|
253
302
|
# This tests the method_missing override
|