flexirest 1.11.0 → 1.11.1
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/build.yml +1 -4
- data/CHANGELOG.md +6 -0
- data/flexirest.gemspec +1 -0
- data/lib/flexirest/caching.rb +8 -1
- data/lib/flexirest/version.rb +1 -1
- data/spec/lib/caching_spec.rb +55 -26
- data/spec/spec_helper.rb +1 -0
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '036069384b97e0fbcf4e73c9e75154569cffbb9cbfcb8dfcda4ccfc4ef75cca2'
|
4
|
+
data.tar.gz: 3099f07f5284601a68ebba405a60e485975635b5306b72f2ead2090509bdb901
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 18d64a00ceea9f1a9ee61dcdaedf64dbcc8eae7b9f4f3d20943e7b9209dd7d98acd08138a9c149d0f7cb7aa03740131030580c45f4d153e2f47df999e6415a61
|
7
|
+
data.tar.gz: 026a430bdc41b68adc6e46c42dc69983fca9ef431fb3cc068c96fb3714c687209393d15e66879bb46c3f26ba3f9e38dd08b94620a7d8b2f20d392f08690031fd
|
data/.github/workflows/build.yml
CHANGED
@@ -24,10 +24,7 @@ jobs:
|
|
24
24
|
steps:
|
25
25
|
- uses: actions/checkout@v2
|
26
26
|
- name: Set up Ruby
|
27
|
-
|
28
|
-
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
29
|
-
# uses: ruby/setup-ruby@v1
|
30
|
-
uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
|
27
|
+
uses: ruby/setup-ruby@v1
|
31
28
|
with:
|
32
29
|
ruby-version: ${{ matrix.ruby-version }}
|
33
30
|
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
data/CHANGELOG.md
CHANGED
data/flexirest.gemspec
CHANGED
@@ -36,6 +36,7 @@ Gem::Specification.new do |spec|
|
|
36
36
|
spec.add_development_dependency 'faraday-typhoeus'
|
37
37
|
spec.add_development_dependency 'activemodel'
|
38
38
|
spec.add_development_dependency 'rest-client'
|
39
|
+
spec.add_development_dependency 'timecop'
|
39
40
|
|
40
41
|
spec.add_runtime_dependency "mime-types"
|
41
42
|
spec.add_runtime_dependency "multi_json"
|
data/lib/flexirest/caching.rb
CHANGED
@@ -74,7 +74,14 @@ module Flexirest
|
|
74
74
|
cached_response.etag = "#{headers[:etag]}" if headers[:etag]
|
75
75
|
cached_response.expires = Time.parse(headers[:expires]) rescue nil if headers[:expires]
|
76
76
|
if cached_response.etag.present? || cached_response.expires
|
77
|
-
|
77
|
+
options = {}
|
78
|
+
if cached_response.expires.present?
|
79
|
+
exp_in_seconds = cached_response.expires.utc - Time.now.utc
|
80
|
+
return unless exp_in_seconds.positive?
|
81
|
+
|
82
|
+
options[:expires_in] = exp_in_seconds
|
83
|
+
end
|
84
|
+
cache_store.write(key, Marshal.dump(cached_response), options)
|
78
85
|
end
|
79
86
|
end
|
80
87
|
end
|
data/lib/flexirest/version.rb
CHANGED
data/spec/lib/caching_spec.rb
CHANGED
@@ -72,28 +72,21 @@ describe Flexirest::Caching do
|
|
72
72
|
end
|
73
73
|
|
74
74
|
it "should use a custom cache store if a valid one is manually set" do
|
75
|
-
class CachingExampleCacheStore1
|
76
|
-
def read(key) ; end
|
77
|
-
def write(key, value, options={}) ; end
|
78
|
-
def fetch(key, &block) ; end
|
79
|
-
end
|
75
|
+
class CachingExampleCacheStore1 < ActiveSupport::Cache::MemoryStore; end
|
80
76
|
cache_store = CachingExampleCacheStore1.new
|
81
77
|
Flexirest::Base.cache_store = cache_store
|
82
78
|
expect(Flexirest::Base.cache_store).to eq(cache_store)
|
83
79
|
end
|
84
80
|
|
85
81
|
it "should error if you try to use a custom cache store that doesn't match the required interface" do
|
86
|
-
class CachingExampleCacheStore2
|
87
|
-
|
88
|
-
def fetch(key, &block) ; end
|
82
|
+
class CachingExampleCacheStore2 < ActiveSupport::Cache::MemoryStore
|
83
|
+
undef_method :read
|
89
84
|
end
|
90
|
-
class CachingExampleCacheStore3
|
91
|
-
|
92
|
-
def fetch(key, &block) ; end
|
85
|
+
class CachingExampleCacheStore3 < ActiveSupport::Cache::MemoryStore
|
86
|
+
undef_method :write
|
93
87
|
end
|
94
|
-
class CachingExampleCacheStore4
|
95
|
-
|
96
|
-
def write(key, value, options={}) ; end
|
88
|
+
class CachingExampleCacheStore4 < ActiveSupport::Cache::MemoryStore
|
89
|
+
undef_method :fetch
|
97
90
|
end
|
98
91
|
|
99
92
|
expect{ Flexirest::Base.cache_store = CachingExampleCacheStore2.new }.to raise_error(Flexirest::InvalidCacheStoreException)
|
@@ -109,11 +102,7 @@ describe Flexirest::Caching do
|
|
109
102
|
context "Reading/writing to the cache" do
|
110
103
|
before :each do
|
111
104
|
Object.send(:remove_const, :CachingExampleCacheStore5) if defined?(CachingExampleCacheStore5)
|
112
|
-
class CachingExampleCacheStore5
|
113
|
-
def read(key) ; end
|
114
|
-
def write(key, value, options={}) ; end
|
115
|
-
def fetch(key, &block) ; end
|
116
|
-
end
|
105
|
+
class CachingExampleCacheStore5 < ActiveSupport::Cache::MemoryStore; end
|
117
106
|
|
118
107
|
class Person < Flexirest::Base
|
119
108
|
perform_caching true
|
@@ -122,7 +111,7 @@ describe Flexirest::Caching do
|
|
122
111
|
put :save_all, "/"
|
123
112
|
end
|
124
113
|
|
125
|
-
Person.cache_store = CachingExampleCacheStore5.new
|
114
|
+
Person.cache_store = CachingExampleCacheStore5.new({ expires_in: 1.day.to_i }) # default cache expiration
|
126
115
|
|
127
116
|
@etag = "6527914a91e0c5769f6de281f25bd891"
|
128
117
|
@cached_object = Person.new(first_name:"Johnny")
|
@@ -173,7 +162,7 @@ describe Flexirest::Caching do
|
|
173
162
|
expect(result.first_name).to eq new_name
|
174
163
|
end
|
175
164
|
|
176
|
-
it "should read from the cache store, and not call the server if there's a hard expiry" do
|
165
|
+
it "should read from the cache store, and not call the server if there's a hard expiry not passed yet" do
|
177
166
|
cached_response = Flexirest::CachedResponse.new(
|
178
167
|
status:200,
|
179
168
|
result:@cached_object,
|
@@ -184,6 +173,18 @@ describe Flexirest::Caching do
|
|
184
173
|
expect(ret.first_name).to eq("Johnny")
|
185
174
|
end
|
186
175
|
|
176
|
+
it "should not read from the cache store, and call the server if there's a hard expiry already passed" do
|
177
|
+
cached_response = Flexirest::CachedResponse.new(
|
178
|
+
status:200,
|
179
|
+
result:@cached_object,
|
180
|
+
expires:Time.now + 30)
|
181
|
+
Timecop.travel(Time.now + 60)
|
182
|
+
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(nil)
|
183
|
+
expect_any_instance_of(Flexirest::Connection).to receive(:get).with("/", an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, body:"{\"result\":true}", response_headers:{})))
|
184
|
+
ret = Person.all
|
185
|
+
Timecop.return
|
186
|
+
end
|
187
|
+
|
187
188
|
it "cache read objects shouldn't be marked as changed" do
|
188
189
|
cached_response = Flexirest::CachedResponse.new(
|
189
190
|
status:200,
|
@@ -208,7 +209,7 @@ describe Flexirest::Caching do
|
|
208
209
|
expect(ret.first_name).to eq("Johnny")
|
209
210
|
end
|
210
211
|
|
211
|
-
it "should restore a result iterator from the cache store, if there's a hard expiry" do
|
212
|
+
it "should restore a result iterator from the cache store, if there's a hard expiry not passed yet" do
|
212
213
|
class CachingExample3 < Flexirest::Base ; end
|
213
214
|
object = Flexirest::ResultIterator.new(double(status: 200))
|
214
215
|
object << CachingExample3.new(first_name:"Johnny")
|
@@ -226,6 +227,26 @@ describe Flexirest::Caching do
|
|
226
227
|
expect(ret._status).to eq(200)
|
227
228
|
end
|
228
229
|
|
230
|
+
it "should not restore a result iterator from the cache store, if there's a hard expiry already passed" do
|
231
|
+
class CachingExample3 < Flexirest::Base ; end
|
232
|
+
object = Flexirest::ResultIterator.new(double(status: 200))
|
233
|
+
object << CachingExample3.new(first_name:"Johnny")
|
234
|
+
object << CachingExample3.new(first_name:"Billy")
|
235
|
+
etag = "6527914a91e0c5769f6de281f25bd891"
|
236
|
+
cached_response = Flexirest::CachedResponse.new(
|
237
|
+
status:200,
|
238
|
+
result:object,
|
239
|
+
etag:etag,
|
240
|
+
expires:Time.now + 30)
|
241
|
+
Timecop.travel(Time.now + 60)
|
242
|
+
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(nil)
|
243
|
+
expect_any_instance_of(Flexirest::Connection).to receive(:get).with("/", an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, body:"[{\"first_name\":\"Billy\"}]", response_headers:{})))
|
244
|
+
ret = Person.all
|
245
|
+
expect(ret.first.first_name).to eq("Billy")
|
246
|
+
expect(ret._status).to eq(200)
|
247
|
+
Timecop.return
|
248
|
+
end
|
249
|
+
|
229
250
|
it "should not write the response to the cache unless it has caching headers" do
|
230
251
|
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(nil)
|
231
252
|
expect_any_instance_of(CachingExampleCacheStore5).not_to receive(:write)
|
@@ -233,9 +254,9 @@ describe Flexirest::Caching do
|
|
233
254
|
Person.all
|
234
255
|
end
|
235
256
|
|
236
|
-
it "should write the response to the cache if there's an etag" do
|
257
|
+
it "should write the response to the cache without expires_in option if there's an etag" do
|
237
258
|
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(nil)
|
238
|
-
expect_any_instance_of(CachingExampleCacheStore5).to receive(:write).once.with("Person:/", an_instance_of(String),
|
259
|
+
expect_any_instance_of(CachingExampleCacheStore5).to receive(:write).once.with("Person:/", an_instance_of(String), hash_excluding(:expires_in))
|
239
260
|
expect_any_instance_of(Flexirest::Connection).to receive(:get).with("/", an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, body:"{\"result\":true}", response_headers:{etag:"1234567890"})))
|
240
261
|
Person.perform_caching true
|
241
262
|
Person.all
|
@@ -264,14 +285,22 @@ describe Flexirest::Caching do
|
|
264
285
|
end
|
265
286
|
end
|
266
287
|
|
267
|
-
it "should write the response to the cache if there's a hard expiry" do
|
288
|
+
it "should write the response to the cache with expires_in option if there's a hard expiry in the future" do
|
268
289
|
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(nil)
|
269
|
-
expect_any_instance_of(CachingExampleCacheStore5).to receive(:write).once.with("Person:/", an_instance_of(String),
|
290
|
+
expect_any_instance_of(CachingExampleCacheStore5).to receive(:write).once.with("Person:/", an_instance_of(String), hash_including(:expires_in))
|
270
291
|
expect_any_instance_of(Flexirest::Connection).to receive(:get).with("/", an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, body:"{\"result\":true}", response_headers:{expires:(Time.now + 30).rfc822})))
|
271
292
|
Person.perform_caching = true
|
272
293
|
Person.all
|
273
294
|
end
|
274
295
|
|
296
|
+
it "should not write the response to the cache if there's a hard expiry in the past" do
|
297
|
+
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(nil)
|
298
|
+
expect_any_instance_of(CachingExampleCacheStore5).not_to receive(:write)
|
299
|
+
expect_any_instance_of(Flexirest::Connection).to receive(:get).with("/", an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, body:"{\"result\":true}", response_headers:{expires:(Time.now - 10).rfc822})))
|
300
|
+
Person.perform_caching = true
|
301
|
+
Person.all
|
302
|
+
end
|
303
|
+
|
275
304
|
it "should not write the response to the cache if there's an invalid expiry" do
|
276
305
|
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(nil)
|
277
306
|
expect_any_instance_of(CachingExampleCacheStore5).to_not receive(:write).once.with("Person:/", an_instance_of(String), an_instance_of(Hash))
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flexirest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.11.
|
4
|
+
version: 1.11.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Jeffries
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-06-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -178,6 +178,20 @@ dependencies:
|
|
178
178
|
- - ">="
|
179
179
|
- !ruby/object:Gem::Version
|
180
180
|
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: timecop
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
181
195
|
- !ruby/object:Gem::Dependency
|
182
196
|
name: mime-types
|
183
197
|
requirement: !ruby/object:Gem::Requirement
|
@@ -393,7 +407,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
393
407
|
- !ruby/object:Gem::Version
|
394
408
|
version: '0'
|
395
409
|
requirements: []
|
396
|
-
rubygems_version: 3.
|
410
|
+
rubygems_version: 3.4.6
|
397
411
|
signing_key:
|
398
412
|
specification_version: 4
|
399
413
|
summary: This gem is for accessing REST services in a flexible way. ActiveResource
|