cached_resource 7.0.0 → 7.2.0

Sign up to get free protection for your applications and to get access to all the features.
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