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