object-cache 0.0.3 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1d2f1ec4b3467a87297e809f094d3f75461b3fa9
4
- data.tar.gz: bf7eef92986a7ddb52c5f7ec2aa3110ddbaa791d
2
+ SHA256:
3
+ metadata.gz: 5702bb0b9df058e9fd36b86a712f11b716dc0d8e8ff3d05378a1b204f18bb6dc
4
+ data.tar.gz: a669e8209d07ce571313e6b63c7643e064e1e0b78ea39e8397b53a583016f49e
5
5
  SHA512:
6
- metadata.gz: 323e1806f012635837d50ac2111d607232714308376d16e9ab32718cc2217fe760d745298b3e20165b1d3e70f339b90acca9aada9ec81cf44f5b75e971403006
7
- data.tar.gz: 7b0cd11b83029e6e2b9701804a7426679e6002578777192916301c75af7faaf9780a61acd5ef8a32a8df52de45e977a5d86be1954f1a56dfdbd876bb7ea15dc7
6
+ metadata.gz: a59277f8c32bba979c8d5184c512b41b4faa816f1a9c1ed07af1ca826d69131f92980057e8ad9bd3975cb53bc5953867e4a3577eb84a7b12c592612c3483a9f0
7
+ data.tar.gz: 79b741e82962f83510437e93aa4d683bb59571452070f30fc55333c418395916d45b3363a70c775075908e4b26b9ae032222f0970382a5cf8d8813954742aac6
@@ -1,10 +1,20 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.3
2
+ TargetRubyVersion: 2.4
3
3
  Exclude:
4
4
  - '.wercker/**/*'
5
5
 
6
6
  Metrics/MethodLength:
7
- Max: 15
7
+ Max: 20
8
8
 
9
9
  Metrics/LineLength:
10
10
  Max: 100
11
+
12
+ Style/RescueStandardError:
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
@@ -1,3 +1,4 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  source 'https://rubygems.org'
3
4
  gemspec
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.del('hello_')
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 extend `Object` with a `cache` method, for
213
- convenient access to the cache object:
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(--display-cop-names --extra-details --display-style-guide)
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(test rubocop)
17
+ task default: %i[test rubocop]
@@ -44,29 +44,37 @@ class Cache
44
44
  # Cache.new { item } # item is only stored once, and then always
45
45
  # # retrieved, even if it is a different item
46
46
  #
47
- def new(key = nil, ttl: default_ttl, key_prefix: default_key_prefix)
47
+ def new(key = nil, ttl: default_ttl, key_prefix: default_key_prefix, &block)
48
48
  return yield unless replica
49
49
 
50
- key = build_key(key, key_prefix, Proc.new)
51
-
52
- if (cached_value = replica.get(key)).nil?
53
- yield.tap { |value| update_cache(key, value, ttl: ttl) }
54
- else
55
- Marshal.load(cached_value)
50
+ begin
51
+ key = build_key(key, key_prefix, block)
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)
69
- replica.exists(key)
77
+ replica.exists?(key)
70
78
  rescue
71
79
  false
72
80
  end
@@ -89,7 +97,8 @@ class Cache
89
97
  end
90
98
 
91
99
  def replicas
92
- [backend.is_a?(Hash) ? backend[:replicas] : backend].flatten
100
+ replicas = backend.is_a?(Hash) ? backend[:replicas] : backend
101
+ replicas.respond_to?(:sample) ? replicas : [replicas]
93
102
  end
94
103
 
95
104
  def replica
@@ -97,7 +106,7 @@ class Cache
97
106
  end
98
107
 
99
108
  def build_key(key, key_prefix, proc)
100
- hash = Digest::SHA1.hexdigest([key, proc.source_location].flatten.join)[0..5]
109
+ hash = Digest::SHA1.hexdigest([key, proc.source_location].flatten.join)[0..11]
101
110
  prefix = build_key_prefix(key_prefix, proc)
102
111
 
103
112
  [prefix, hash].compact.join('_')
@@ -106,7 +115,7 @@ class Cache
106
115
  def build_key_prefix(key_prefix, proc)
107
116
  case key_prefix
108
117
  when :method_name
109
- location = caller_locations.find { |l| "#{l.path}#{l.lineno}" == proc.source_location.join }
118
+ location = caller_locations.find { |l| proc.source_location.join == "#{l.path}#{l.lineno}" }
110
119
  location&.base_label
111
120
  when :class_name
112
121
  proc.binding.receiver.class.to_s
@@ -1,11 +1,10 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'object/cache'
3
4
 
4
5
  # :no-doc:
5
- class Object
6
+ module Kernel
6
7
  def cache(key = nil, **options, &block)
7
- block = -> { self } unless block_given?
8
-
9
8
  Cache.new(key, **options, &block)
10
9
  end
11
10
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Cache
4
- VERSION = '0.0.3'
4
+ VERSION = '0.1.2'
5
5
  end
@@ -1,27 +1,27 @@
1
1
  # frozen_string_literal: true
2
- # encoding: utf-8
3
- lib = File.expand_path('../lib', __FILE__)
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require 'object/cache'
6
6
 
7
7
  Gem::Specification.new do |spec|
8
8
  spec.name = 'object-cache'
9
9
  spec.version = Cache::VERSION
10
- spec.authors = %w(Jean Mertz)
11
- spec.email = %w(jean@mertz.fm)
10
+ spec.authors = %w[Jean Mertz]
11
+ spec.email = %w[jean@mertz.fm]
12
12
 
13
13
  spec.summary = 'Caching of objects, using a Redis store.'
14
14
  spec.description = 'Easily cache objects in Ruby, using a Redis store backend'
15
15
  spec.homepage = 'https://github.com/blendle/object-cache'
16
16
  spec.license = 'MIT'
17
17
  spec.files = `git ls-files -z`.split("\x0")
18
- spec.require_paths = %w(lib)
18
+ spec.require_paths = %w[lib]
19
19
 
20
- spec.add_development_dependency 'bundler', '~> 1.12'
20
+ spec.add_development_dependency 'bundler', '~> 2.1'
21
21
  spec.add_development_dependency 'm', '~> 1.5'
22
- spec.add_development_dependency 'minitest', '~> 5.0'
22
+ spec.add_development_dependency 'minitest'
23
23
  spec.add_development_dependency 'mock_redis', '~> 0.16'
24
- spec.add_development_dependency 'pry', '~> 0.10'
25
- spec.add_development_dependency 'rake', '~> 10.0'
26
- spec.add_development_dependency 'rubocop', '~> 0.40'
24
+ spec.add_development_dependency 'pry'
25
+ spec.add_development_dependency 'rake'
26
+ spec.add_development_dependency 'rubocop'
27
27
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
3
4
 
4
5
  require 'mock_redis'
5
6
  require 'object/cache'
@@ -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 'hello world', Cache.new { 'hello world' }
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 'hello world', cache { 'hello world' }
98
- assert Object.send(:remove_method, :cache)
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 Object.send(:remove_method, :cache)
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,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: object-cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean
8
8
  - Mertz
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-05-26 00:00:00.000000000 Z
12
+ date: 2020-09-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -17,14 +17,14 @@ dependencies:
17
17
  requirements:
18
18
  - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: '1.12'
20
+ version: '2.1'
21
21
  type: :development
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: '1.12'
27
+ version: '2.1'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: m
30
30
  requirement: !ruby/object:Gem::Requirement
@@ -43,16 +43,16 @@ dependencies:
43
43
  name: minitest
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - "~>"
46
+ - - ">="
47
47
  - !ruby/object:Gem::Version
48
- version: '5.0'
48
+ version: '0'
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - "~>"
53
+ - - ">="
54
54
  - !ruby/object:Gem::Version
55
- version: '5.0'
55
+ version: '0'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: mock_redis
58
58
  requirement: !ruby/object:Gem::Requirement
@@ -71,44 +71,44 @@ dependencies:
71
71
  name: pry
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - "~>"
74
+ - - ">="
75
75
  - !ruby/object:Gem::Version
76
- version: '0.10'
76
+ version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - "~>"
81
+ - - ">="
82
82
  - !ruby/object:Gem::Version
83
- version: '0.10'
83
+ version: '0'
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: rake
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
- - - "~>"
88
+ - - ">="
89
89
  - !ruby/object:Gem::Version
90
- version: '10.0'
90
+ version: '0'
91
91
  type: :development
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
- - - "~>"
95
+ - - ">="
96
96
  - !ruby/object:Gem::Version
97
- version: '10.0'
97
+ version: '0'
98
98
  - !ruby/object:Gem::Dependency
99
99
  name: rubocop
100
100
  requirement: !ruby/object:Gem::Requirement
101
101
  requirements:
102
- - - "~>"
102
+ - - ">="
103
103
  - !ruby/object:Gem::Version
104
- version: '0.40'
104
+ version: '0'
105
105
  type: :development
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
- - - "~>"
109
+ - - ">="
110
110
  - !ruby/object:Gem::Version
111
- version: '0.40'
111
+ version: '0'
112
112
  description: Easily cache objects in Ruby, using a Redis store backend
113
113
  email:
114
114
  - jean@mertz.fm
@@ -118,7 +118,6 @@ extra_rdoc_files: []
118
118
  files:
119
119
  - ".gitignore"
120
120
  - ".rubocop.yml"
121
- - ".wercker.yml"
122
121
  - CODE_OF_CONDUCT.md
123
122
  - Gemfile
124
123
  - LICENSE.txt
@@ -133,7 +132,7 @@ homepage: https://github.com/blendle/object-cache
133
132
  licenses:
134
133
  - MIT
135
134
  metadata: {}
136
- post_install_message:
135
+ post_install_message:
137
136
  rdoc_options: []
138
137
  require_paths:
139
138
  - lib
@@ -148,9 +147,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
148
147
  - !ruby/object:Gem::Version
149
148
  version: '0'
150
149
  requirements: []
151
- rubyforge_project:
152
- rubygems_version: 2.6.4
153
- signing_key:
150
+ rubygems_version: 3.1.2
151
+ signing_key:
154
152
  specification_version: 4
155
153
  summary: Caching of objects, using a Redis store.
156
154
  test_files: []
@@ -1,7 +0,0 @@
1
- box: ruby:2.3
2
- build:
3
- steps:
4
- - bundle-install
5
- - script:
6
- name: tests
7
- code: bundle exec rake