object-cache 0.0.5 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +11 -1
- data/Gemfile +1 -0
- data/README.md +4 -12
- data/Rakefile +3 -2
- data/lib/object/cache.rb +25 -17
- data/lib/object/cache/core_extension.rb +2 -3
- data/lib/object/cache/version.rb +1 -1
- data/object-cache.gemspec +4 -3
- data/test/cache_test.rb +54 -17
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1eca8358ecaf741c5815a28a6647a528b316df8c
|
4
|
+
data.tar.gz: af038164c54204cc910039bc035d501e729ec69a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 338d80cb2a6fd6c1720003655d23770074cca0a0df1f958805ffcf6987016748aa1cb39e8ad59b0fdca0227a19f9810dd026c3c8786e861c26d6828e8d3502d0
|
7
|
+
data.tar.gz: 88d4a44e5d94dc74bcb46d4ce81056871dd9c9e1a592ff8a929f1dc8347fadefdd1399072eec16e5e876f2f22d2c2ef8d4a90344f0986131c78eac05346b36f5
|
data/.rubocop.yml
CHANGED
@@ -4,7 +4,17 @@ AllCops:
|
|
4
4
|
- '.wercker/**/*'
|
5
5
|
|
6
6
|
Metrics/MethodLength:
|
7
|
-
Max:
|
7
|
+
Max: 20
|
8
8
|
|
9
9
|
Metrics/LineLength:
|
10
10
|
Max: 100
|
11
|
+
|
12
|
+
Lint/RescueWithoutErrorClass:
|
13
|
+
Exclude:
|
14
|
+
- 'lib/object/cache.rb'
|
15
|
+
- 'test/cache_test.rb'
|
16
|
+
|
17
|
+
Security/MarshalLoad:
|
18
|
+
Exclude:
|
19
|
+
- 'lib/object/cache.rb'
|
20
|
+
- 'test/cache_test.rb'
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -157,7 +157,8 @@ Cache.backend.keys # => ["hello_22abcc"]
|
|
157
157
|
This allows you to selectively purge keys from Redis:
|
158
158
|
|
159
159
|
```ruby
|
160
|
-
Cache.backend.
|
160
|
+
keys = Cache.backend.keys('hello_*')
|
161
|
+
Cache.backend.del(keys)
|
161
162
|
```
|
162
163
|
|
163
164
|
You can also use the special value `:method_name` to dynamically set the key
|
@@ -209,8 +210,8 @@ from the primary instance.
|
|
209
210
|
|
210
211
|
#### core extension
|
211
212
|
|
212
|
-
Finally, if you want, you can
|
213
|
-
|
213
|
+
Finally, if you want, you can use the `cache` method, for convenient
|
214
|
+
access to the cache object:
|
214
215
|
|
215
216
|
```ruby
|
216
217
|
require 'object/cache/core_extension'
|
@@ -220,15 +221,6 @@ cache('hello', ttl: 60) { 'hello world' }
|
|
220
221
|
Cache.new('hello', ttl: 60) { 'hello world' }
|
221
222
|
```
|
222
223
|
|
223
|
-
You can also call this method directly on any instances inheriting from
|
224
|
-
`Object`:
|
225
|
-
|
226
|
-
```ruby
|
227
|
-
require 'object/cache/core_extension'
|
228
|
-
|
229
|
-
'hello world'.cache(ttl: 60)
|
230
|
-
```
|
231
|
-
|
232
224
|
That's it!
|
233
225
|
|
234
226
|
## License
|
data/Rakefile
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'bundler/gem_tasks'
|
3
4
|
require 'rake/testtask'
|
4
5
|
require 'rubocop/rake_task'
|
5
6
|
|
6
7
|
RuboCop::RakeTask.new do |t|
|
7
|
-
t.options = %w
|
8
|
+
t.options = %w[--display-cop-names --extra-details --display-style-guide]
|
8
9
|
end
|
9
10
|
|
10
11
|
Rake::TestTask.new(:test) do |t|
|
@@ -13,4 +14,4 @@ Rake::TestTask.new(:test) do |t|
|
|
13
14
|
t.test_files = FileList['test/**/*_test.rb']
|
14
15
|
end
|
15
16
|
|
16
|
-
task default: %i
|
17
|
+
task default: %i[test rubocop]
|
data/lib/object/cache.rb
CHANGED
@@ -47,22 +47,30 @@ class Cache
|
|
47
47
|
def new(key = nil, ttl: default_ttl, key_prefix: default_key_prefix)
|
48
48
|
return yield unless replica
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
50
|
+
begin
|
51
|
+
key = build_key(key, key_prefix, Proc.new)
|
52
|
+
|
53
|
+
if (cached_value = replica.get(key)).nil?
|
54
|
+
yield.tap do |value|
|
55
|
+
begin
|
56
|
+
update_cache(key, value, ttl: ttl)
|
57
|
+
rescue TypeError
|
58
|
+
# if `TypeError` is raised, the data could not be Marshal dumped. In that
|
59
|
+
# case, delete anything left in the cache store, and get the data without
|
60
|
+
# caching.
|
61
|
+
#
|
62
|
+
delete(key)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
else
|
66
|
+
begin
|
67
|
+
Marshal.load(cached_value)
|
68
|
+
rescue
|
69
|
+
delete(key)
|
70
|
+
yield
|
71
|
+
end
|
72
|
+
end
|
56
73
|
end
|
57
|
-
rescue TypeError
|
58
|
-
# if `TypeError` is raised, the data could not be Marshal dumped. In that
|
59
|
-
# case, delete anything left in the cache store, and get the data without
|
60
|
-
# caching.
|
61
|
-
#
|
62
|
-
delete(key)
|
63
|
-
yield
|
64
|
-
rescue
|
65
|
-
yield
|
66
74
|
end
|
67
75
|
|
68
76
|
def include?(key)
|
@@ -107,8 +115,8 @@ class Cache
|
|
107
115
|
def build_key_prefix(key_prefix, proc)
|
108
116
|
case key_prefix
|
109
117
|
when :method_name
|
110
|
-
location = caller_locations.find { |l| "#{l.path}#{l.lineno}"
|
111
|
-
location
|
118
|
+
location = caller_locations.find { |l| proc.source_location.join == "#{l.path}#{l.lineno}" }
|
119
|
+
location&.base_label
|
112
120
|
when :class_name
|
113
121
|
proc.binding.receiver.class.to_s
|
114
122
|
else
|
data/lib/object/cache/version.rb
CHANGED
data/object-cache.gemspec
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
# encoding: utf-8
|
3
|
+
|
3
4
|
lib = File.expand_path('../lib', __FILE__)
|
4
5
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
6
|
require 'object/cache'
|
@@ -7,15 +8,15 @@ require 'object/cache'
|
|
7
8
|
Gem::Specification.new do |spec|
|
8
9
|
spec.name = 'object-cache'
|
9
10
|
spec.version = Cache::VERSION
|
10
|
-
spec.authors = %w
|
11
|
-
spec.email = %w
|
11
|
+
spec.authors = %w[Jean Mertz]
|
12
|
+
spec.email = %w[jean@mertz.fm]
|
12
13
|
|
13
14
|
spec.summary = 'Caching of objects, using a Redis store.'
|
14
15
|
spec.description = 'Easily cache objects in Ruby, using a Redis store backend'
|
15
16
|
spec.homepage = 'https://github.com/blendle/object-cache'
|
16
17
|
spec.license = 'MIT'
|
17
18
|
spec.files = `git ls-files -z`.split("\x0")
|
18
|
-
spec.require_paths = %w
|
19
|
+
spec.require_paths = %w[lib]
|
19
20
|
|
20
21
|
spec.add_development_dependency 'bundler', '~> 1.12'
|
21
22
|
spec.add_development_dependency 'm', '~> 1.5'
|
data/test/cache_test.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
3
4
|
|
4
5
|
require 'mock_redis'
|
@@ -21,7 +22,7 @@ class CacheTest < Minitest::Test # rubocop:disable Metrics/ClassLength
|
|
21
22
|
end
|
22
23
|
|
23
24
|
def test_cache_returns_object
|
24
|
-
assert_equal
|
25
|
+
assert_equal('hello world', Cache.new { 'hello world' })
|
25
26
|
end
|
26
27
|
|
27
28
|
def test_cache_stores_object
|
@@ -94,28 +95,15 @@ class CacheTest < Minitest::Test # rubocop:disable Metrics/ClassLength
|
|
94
95
|
|
95
96
|
def test_core_extension
|
96
97
|
load 'object/cache/core_extension.rb'
|
97
|
-
assert_equal
|
98
|
-
assert
|
98
|
+
assert_equal('hello world', cache { 'hello world' })
|
99
|
+
assert Kernel.send(:remove_method, :cache)
|
99
100
|
end
|
100
101
|
|
101
102
|
def test_core_extension_options
|
102
103
|
load 'object/cache/core_extension.rb'
|
103
104
|
cache(ttl: 60) { 'hello world' }
|
104
105
|
assert_equal 60, redis.ttl(redis.keys.first)
|
105
|
-
assert
|
106
|
-
end
|
107
|
-
|
108
|
-
def test_core_extension_on_objects
|
109
|
-
load 'object/cache/core_extension.rb'
|
110
|
-
assert_equal 'hello world', 'hello world'.cache
|
111
|
-
assert Object.send(:remove_method, :cache)
|
112
|
-
end
|
113
|
-
|
114
|
-
def test_core_extension_on_objects_with_arguments
|
115
|
-
load 'object/cache/core_extension.rb'
|
116
|
-
'hello world'.cache(ttl: 30)
|
117
|
-
assert_equal 30, redis.ttl(redis.keys.first)
|
118
|
-
assert Object.send(:remove_method, :cache)
|
106
|
+
assert Kernel.send(:remove_method, :cache)
|
119
107
|
end
|
120
108
|
|
121
109
|
def test_backend_with_replicas
|
@@ -183,4 +171,53 @@ class CacheTest < Minitest::Test # rubocop:disable Metrics/ClassLength
|
|
183
171
|
Cache.new(key_prefix: :class_name) { 'hello world' }
|
184
172
|
assert_match(/^CacheTest/, redis.keys.first)
|
185
173
|
end
|
174
|
+
|
175
|
+
def test_unset_backend
|
176
|
+
Cache.backend = nil
|
177
|
+
val = 0
|
178
|
+
block = -> { val += 1 }
|
179
|
+
Cache.new(&block)
|
180
|
+
Cache.backend = MockRedis.new
|
181
|
+
|
182
|
+
assert_equal 1, val
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_unset_backend_raising_type_error
|
186
|
+
Cache.backend = nil
|
187
|
+
val = 0
|
188
|
+
begin
|
189
|
+
Cache.new do
|
190
|
+
val += 1
|
191
|
+
raise TypeError
|
192
|
+
end
|
193
|
+
rescue
|
194
|
+
nil
|
195
|
+
end
|
196
|
+
|
197
|
+
Cache.backend = MockRedis.new
|
198
|
+
assert_equal 1, val
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_single_yield_on_failure
|
202
|
+
val = 0
|
203
|
+
begin
|
204
|
+
Cache.new do
|
205
|
+
val += 1
|
206
|
+
raise TypeError
|
207
|
+
end
|
208
|
+
rescue
|
209
|
+
nil
|
210
|
+
end
|
211
|
+
|
212
|
+
assert_equal 1, val
|
213
|
+
end
|
214
|
+
|
215
|
+
def test_yield_when_marshal_load_fails
|
216
|
+
testing = -> { Cache.new(key_prefix: 'marshal') { 'hello world' } }
|
217
|
+
|
218
|
+
assert_equal 'hello world', testing.call
|
219
|
+
redis.set(redis.keys('marshal*').first, 'garbage')
|
220
|
+
assert_equal 'hello world', testing.call
|
221
|
+
assert_empty redis.keys('marshal*')
|
222
|
+
end
|
186
223
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: object-cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2017-09-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -149,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
149
149
|
version: '0'
|
150
150
|
requirements: []
|
151
151
|
rubyforge_project:
|
152
|
-
rubygems_version: 2.6.
|
152
|
+
rubygems_version: 2.6.11
|
153
153
|
signing_key:
|
154
154
|
specification_version: 4
|
155
155
|
summary: Caching of objects, using a Redis store.
|