cached_resource 7.0.0 → 7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 945dbe812b6e4fea58b155907076ea3821bf87a7b37312a7301f16f420ed9158
4
- data.tar.gz: f07ca05471ba063bbe38d8ae7a29d6b16c4cd5132066f9c8d9f71d2d06a22c45
3
+ metadata.gz: d1c2150c2dc21cf091c9b26674b3e52a7bd43938318704f7c2f0739a0b9756aa
4
+ data.tar.gz: 2f7b9665c688f2a60b7def43cfafbe2701accded9fcf9aabc371fe91bf78362d
5
5
  SHA512:
6
- metadata.gz: ab3c75b4c0384b7ea516159ce7526e7dcd62443951331302986483403887d7e498528fef972c1268fc9a2dce3fb2d0df56434617ea21db03a3adc3457534527d
7
- data.tar.gz: 21a1220f34e5bb07b5da51648dcbdb521970c801d7aabdcc53a142b4ad5347c0e779c3bd7186891f5bb9e4b9b79bb74df5790b9524cd14f72358d875b293c9db
6
+ metadata.gz: c0c94c6b77f623a49a3259a69a4bb1b1d2d7fc219d590b740d5a86c71f3cfbf7eb783a2e8a2c06631c926bd2679b220341d8fbf03b77a3651d5219a70bb8d779
7
+ data.tar.gz: 207c37429a14511fb788d21bc69e86b01f8f59a303b20aebafb2f07e54aba48546c03a5ac7fa4b99da0bd9b7cd53d385ddb73306c643d9044d113ea638949e61
@@ -15,7 +15,7 @@ permissions:
15
15
  jobs:
16
16
  test:
17
17
 
18
- runs-on: ubuntu-latest
18
+ runs-on: ubuntu-20.04
19
19
 
20
20
  strategy:
21
21
  matrix:
@@ -106,4 +106,4 @@ jobs:
106
106
  TEST_RAILS_VERSION: ${{ matrix.rails-version }}
107
107
  DEBUG: true
108
108
  - name: Run tests
109
- run: bundle exec rake
109
+ run: bundle exec rake
data/FUNDING.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "drips": {
3
+ "ethereum": {
4
+ "ownedBy": "0xe2E9b9B5d0757c26aB477A754788B19b60f2ed83"
5
+ }
6
+ }
7
+ }
data/README.md CHANGED
@@ -25,6 +25,13 @@ CachedResource is designed to be framework agnostic, but will hook into Rails fo
25
25
  | 💎 3.1 | | | | ✅ | ✅ | ✅ |
26
26
  | 💎 3.2 | | | | ✅ | ✅ | ✅ |
27
27
 
28
+ ## Limitations
29
+
30
+ The following are limitations for ActiveResource/Rails versions
31
+
32
+ | ActiveSupport Version | Limitation |
33
+ |---------------------- | ----------------------------------------------------------------------- |
34
+ | 🛤️ 4.X | You cannot chain calls. Ie `Thing.where(fn: 'foo').where(ln: 'bar')`. <br> However, you can still access `original_params` and the `resource_class` and replicate it with <br>`call1 = Thing.where(fn: 'foo')`<br>`call1.resource_class.where(call1.original_params.merge(ln: 'bar'))` |
28
35
 
29
36
  ## Configuration
30
37
 
@@ -37,13 +37,14 @@ module CachedResource
37
37
  cache_read(key) || find_via_reload(key, *arguments)
38
38
  end
39
39
 
40
- # Re/send the request to fetch the resource. Cache the response
41
- # for the request.
40
+ # Re/send the request to fetch the resource
42
41
  def find_via_reload(key, *arguments)
43
42
  object = find_without_cache(*arguments)
43
+ return object unless should_cache?(object)
44
+
44
45
  cache_collection_synchronize(object, *arguments) if cached_resource.collection_synchronize
45
46
  return object if !cached_resource.cache_collections && is_any_collection?(*arguments)
46
- cache_write(key, object)
47
+ cache_write(key, object, *arguments)
47
48
  cache_read(key)
48
49
  end
49
50
 
@@ -52,32 +53,38 @@ module CachedResource
52
53
  # otherwise update an existing collection if possible.
53
54
  def cache_collection_synchronize(object, *arguments)
54
55
  if object.is_a? Enumerable
55
- update_singles_cache(object)
56
+ update_singles_cache(object, *arguments)
56
57
  # update the collection only if this is a subset of it
57
- update_collection_cache(object) unless is_collection?(*arguments)
58
+ update_collection_cache(object, *arguments) unless is_collection?(*arguments)
58
59
  else
59
- update_collection_cache(object)
60
+ update_collection_cache(object, *arguments)
60
61
  end
61
62
  end
62
63
 
63
64
  # Update the cache of singles with an array of updates.
64
- def update_singles_cache(updates)
65
+ def update_singles_cache(updates, *arguments)
65
66
  updates = Array(updates)
66
- updates.each { |object| cache_write(cache_key(object.send(primary_key)), object) }
67
+ updates.each { |object| cache_write(cache_key(object.send(primary_key)), object, *arguments) }
67
68
  end
68
69
 
69
70
  # Update the "mother" collection with an array of updates.
70
- def update_collection_cache(updates)
71
+ def update_collection_cache(updates, *arguments)
71
72
  updates = Array(updates)
72
73
  collection = cache_read(cache_key(cached_resource.collection_arguments))
73
74
 
74
75
  if collection && !updates.empty?
75
76
  index = collection.inject({}) { |hash, object| hash[object.send(primary_key)] = object; hash }
76
77
  updates.each { |object| index[object.send(primary_key)] = object }
77
- cache_write(cache_key(cached_resource.collection_arguments), index.values)
78
+ cache_write(cache_key(cached_resource.collection_arguments), index.values, *arguments)
78
79
  end
79
80
  end
80
81
 
82
+ # Avoid cache nil or [] objects
83
+ def should_cache?(object)
84
+ return false unless cached_resource.enabled
85
+ object.respond_to?(:empty?) ? !object.empty? : !!object
86
+ end
87
+
81
88
  # Determine if the given arguments represent
82
89
  # the entire collection of objects.
83
90
  def is_collection?(*arguments)
@@ -101,7 +108,10 @@ module CachedResource
101
108
  if cache.is_a? Enumerable
102
109
  restored = cache.map { |record| full_dup(record) }
103
110
  next restored unless respond_to?(:collection_parser)
104
- collection_parser.new(restored)
111
+ collection_parser.new(restored).tap do |parser|
112
+ parser.resource_class = self
113
+ parser.original_params = json['original_params']
114
+ end
105
115
  else
106
116
  full_dup(cache)
107
117
  end
@@ -112,8 +122,12 @@ module CachedResource
112
122
  end
113
123
 
114
124
  # Write an entry to the cache for the given key and value.
115
- def cache_write(key, object)
116
- result = cached_resource.cache.write(key, object_to_json(object), :race_condition_ttl => cached_resource.race_condition_ttl, :expires_in => cached_resource.generate_ttl)
125
+ def cache_write(key, object, *arguments)
126
+ options = arguments[1] || {}
127
+ params = options[:params]
128
+ prefix_options, query_options = split_options(params)
129
+
130
+ result = cached_resource.cache.write(key, object_to_json(object, prefix_options, query_options), :race_condition_ttl => cached_resource.race_condition_ttl, :expires_in => cached_resource.generate_ttl)
117
131
  result && cached_resource.logger.info("#{CachedResource::Configuration::LOGGER_PREFIX} WRITE #{key}")
118
132
  result
119
133
  end
@@ -150,21 +164,34 @@ module CachedResource
150
164
  end
151
165
 
152
166
  def json_to_object(json)
153
- if json.is_a? Array
154
- json.map { |attrs|
155
- self.new(attrs["object"], attrs["persistence"]) }
167
+ resource = json['resource']
168
+ if resource.is_a? Array
169
+ resource.map do |attrs|
170
+ self.new(attrs["object"], attrs["persistence"]).tap do |resource|
171
+ resource.prefix_options = json['prefix_options']
172
+ end
173
+ end
156
174
  else
157
- self.new(json["object"], json["persistence"])
175
+ self.new(resource["object"], resource["persistence"]).tap do |resource|
176
+ resource.prefix_options = json['prefix_options']
177
+ end
158
178
  end
159
179
  end
160
180
 
161
- def object_to_json(object)
181
+ def object_to_json(object, prefix_options, query_options)
162
182
  if object.is_a? Enumerable
163
- object.map { |o| { :object => o, :persistence => o.persisted? } }.to_json
183
+ {
184
+ :resource => object.map { |o| { :object => o, :persistence => o.persisted? } },
185
+ :prefix_options => prefix_options,
186
+ :original_params => query_options
187
+ }.to_json
164
188
  elsif object.nil?
165
189
  nil.to_json
166
190
  else
167
- { :object => object, :persistence => object.persisted? }.to_json
191
+ {
192
+ :resource => { :object => object, :persistence => object.persisted? },
193
+ :prefix_options => prefix_options
194
+ }.to_json
168
195
  end
169
196
  end
170
197
  end
@@ -1,3 +1,3 @@
1
1
  module CachedResource
2
- VERSION = "7.0.0"
2
+ VERSION = "7.2.0"
3
3
  end
@@ -18,6 +18,8 @@ describe CachedResource do
18
18
  end
19
19
 
20
20
  @thing = {:thing => {:id => 1, :name => "Ada"}}
21
+ @thing_collection = [{:id => 1, :name => "Ada"}, {:id => 2, :name => "Ada", :major => 'CS'}]
22
+ @thing_collection2 = [{:id => 2, :name => "Ada", :major => 'CS'}]
21
23
  @other_thing = {:thing => {:id => 1, :name => "Ari"}}
22
24
  @thing2 = {:thing => {:id => 2, :name => "Joe"}}
23
25
  @other_thing2 = {:thing => {:id => 2, :name => "Jeb"}}
@@ -31,6 +33,7 @@ describe CachedResource do
31
33
  @other_string_thing_json = @other_string_thing.to_json
32
34
  @date_thing_json = @date_thing.to_json
33
35
  @nil_thing = nil.to_json
36
+ @empty_array_thing = [].to_json
34
37
  @not_the_thing = {:not_the_thing => {:id => 1, :name => "Not"}}
35
38
  @not_the_thing_json = @not_the_thing.to_json
36
39
  end
@@ -57,6 +60,7 @@ describe CachedResource do
57
60
  mock.get "/things/1.json?foo=bar", {}, @thing_json
58
61
  mock.get "/things/fded.json", {}, @string_thing_json
59
62
  mock.get "/things.json?name=42", {}, @nil_thing, 404
63
+ mock.get "/things.json?name=43", {}, @empty_array_thing
60
64
  mock.get "/things/4.json", {}, @date_thing_json
61
65
  mock.get "/not_the_things/1.json", {}, @not_the_thing_json
62
66
  end
@@ -64,15 +68,19 @@ describe CachedResource do
64
68
 
65
69
  it "should cache a response" do
66
70
  result = Thing.find(1)
67
-
68
71
  read_from_cache("thing/1").should == result
69
72
  end
70
73
 
71
- it "should cache a nil response" do
72
- result = Thing.find(:all, :params => { :name => '42' })
74
+ it "shouldn't cache nil response" do
75
+ Thing.find(:all, :params => { :name => '42' })
73
76
  read_from_cache("thing/all/name/42").should == nil
74
77
  end
75
78
 
79
+ it "shouldn't cache [] response" do
80
+ Thing.find(:all, :params => { :name => '43' })
81
+ read_from_cache("thing/all/name/43").should == nil
82
+ end
83
+
76
84
  it "should cache a response for a string primary key" do
77
85
  result = Thing.find("fded")
78
86
  read_from_cache("thing/fded").should == result
@@ -215,13 +223,39 @@ describe CachedResource do
215
223
  cached.should be_instance_of(ActiveResource::Collection)
216
224
  end
217
225
 
218
- it "should return an instance of the collection_parser" do
226
+ it "should return a chainable instance of the collection_parser" do
219
227
  Thing.cached_resource.cache.clear
220
228
  class CustomCollection < ActiveResource::Collection; end
221
229
  Thing.collection_parser = CustomCollection
222
- Thing.all
223
- cached = read_from_cache("thing/all")
230
+
231
+ ActiveResource::HttpMock.respond_to do |mock|
232
+ mock.get "/things.json?name=ada", {}, @thing_collection.to_json
233
+ mock.get "/things.json?major=CS&name=ada", {}, @thing_collection2.to_json
234
+ end
235
+
236
+ non_cached = Thing.where(name: 'ada')
237
+ non_cached.original_params.should == { 'name' => 'ada' }
238
+ non_cached.map(&:id).should == @thing_collection.map { |h| h[:id]}
239
+
240
+ cached = read_from_cache('thing/all/{:params=>{:name=>"ada"}}')
224
241
  cached.should be_instance_of(CustomCollection)
242
+ cached.original_params.should == { 'name' => 'ada' }
243
+ cached.resource_class.should == Thing
244
+ cached.map(&:id).should == @thing_collection.map { |h| h[:id]}
245
+
246
+ if ActiveResource::VERSION::MAJOR < 5
247
+ non_cached = cached.resource_class.where(cached.original_params.merge(major: 'CS'))
248
+ else
249
+ non_cached = cached.where(major: 'CS')
250
+ end
251
+
252
+ non_cached.original_params.should == { 'name' => 'ada', 'major' => 'CS' }
253
+ non_cached.resource_class.should == Thing
254
+ non_cached.map(&:id).should == @thing_collection2.map { |h| h[:id]}
255
+ cached = read_from_cache('thing/all/{:params=>{"name"=>"ada",:major=>"cs"}}')
256
+ cached.original_params.should == { 'name' => 'ada', 'major' => 'CS' }
257
+ cached.resource_class.should == Thing
258
+ cached.map(&:id).should == @thing_collection2.map { |h| h[:id]}
225
259
  end
226
260
  else
227
261
  it "should return an Array" do
@@ -505,14 +539,9 @@ describe CachedResource do
505
539
  end
506
540
  end
507
541
 
508
- it "should cache a response" do
542
+ it "should not cache a response" do
509
543
  result = Thing.find(1)
510
- read_from_cache("thing/1").should == result
511
- end
512
-
513
- it "should cache a response for a string primary key" do
514
- result = Thing.find("fded")
515
- read_from_cache("thing/fded").should == result
544
+ read_from_cache("thing/1").should be_nil
516
545
  end
517
546
 
518
547
  it "should always remake the request" do
@@ -528,42 +557,6 @@ describe CachedResource do
528
557
  Thing.find("fded")
529
558
  ActiveResource::HttpMock.requests.length.should == 2
530
559
  end
531
-
532
- it "should rewrite the cache for each request" do
533
- Thing.find(1)
534
- old_result = read_from_cache("thing/1")
535
-
536
- # change the response
537
- ActiveResource::HttpMock.reset!
538
- ActiveResource::HttpMock.respond_to do |mock|
539
- mock.get "/things/1.json", {}, @other_thing_json
540
- end
541
-
542
- Thing.find(1)
543
- new_result = read_from_cache("thing/1")
544
- # since active resources are equal if and only if they
545
- # are the same object or an instance of the same class,
546
- # not new?, and have the same id.
547
- new_result.name.should_not == old_result.name
548
- end
549
-
550
- it "should rewrite the cache for each request for a string primary key" do
551
- Thing.find("fded")
552
- old_result = read_from_cache("thing/fded")
553
-
554
- # change the response
555
- ActiveResource::HttpMock.reset!
556
- ActiveResource::HttpMock.respond_to do |mock|
557
- mock.get "/things/fded.json", {}, @other_string_thing_json
558
- end
559
-
560
- Thing.find("fded")
561
- new_result = read_from_cache("thing/fded")
562
- # since active resources are equal if and only if they
563
- # are the same object or an instance of the same class,
564
- # not new?, and have the same id.
565
- new_result.name.should_not == old_result.name
566
- end
567
560
  end
568
561
 
569
562
  describe "when cache_collections is disabled" do
data/spec/spec_helper.rb CHANGED
@@ -2,6 +2,7 @@ require 'rubygems'
2
2
  require 'bundler/setup'
3
3
  require 'active_resource'
4
4
  require 'active_support'
5
+ require 'active_support/time'
5
6
 
6
7
  $:.unshift(File.dirname(__FILE__) + '/../lib')
7
8
  require 'cached_resource'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cached_resource
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.0
4
+ version: 7.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Morgan Brown
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-04 00:00:00.000000000 Z
11
+ date: 2024-03-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activeresource
@@ -89,6 +89,7 @@ files:
89
89
  - ".github/workflows/ruby.yml"
90
90
  - ".gitignore"
91
91
  - ".rspec"
92
+ - FUNDING.json
92
93
  - Gemfile
93
94
  - LICENSE
94
95
  - README.md
@@ -132,4 +133,8 @@ rubygems_version: 3.1.6
132
133
  signing_key:
133
134
  specification_version: 4
134
135
  summary: Caching for ActiveResource
135
- test_files: []
136
+ test_files:
137
+ - spec/cached_resource/cached_resource_spec.rb
138
+ - spec/cached_resource/caching_spec.rb
139
+ - spec/cached_resource/configuration_spec.rb
140
+ - spec/spec_helper.rb