active_rest_client 1.0.9 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +22 -0
- data/active_rest_client.gemspec +1 -0
- data/lib/active_rest_client/base.rb +5 -1
- data/lib/active_rest_client/caching.rb +6 -5
- data/lib/active_rest_client/configuration.rb +6 -0
- data/lib/active_rest_client/connection_manager.rb +15 -0
- data/lib/active_rest_client/proxy_base.rb +36 -2
- data/lib/active_rest_client/request.rb +54 -45
- data/lib/active_rest_client/request_delegator.rb +44 -0
- data/lib/active_rest_client/result_iterator.rb +4 -3
- data/lib/active_rest_client/validation.rb +1 -1
- data/lib/active_rest_client/version.rb +1 -1
- data/lib/active_rest_client.rb +1 -0
- data/spec/lib/base_spec.rb +34 -18
- data/spec/lib/caching_spec.rb +5 -5
- data/spec/lib/configuration_spec.rb +24 -0
- data/spec/lib/connection_manager_spec.rb +7 -0
- data/spec/lib/instrumentation_spec.rb +1 -1
- data/spec/lib/proxy_spec.rb +7 -7
- data/spec/lib/request_spec.rb +117 -60
- data/spec/lib/result_iterator_spec.rb +8 -1
- data/spec/lib/validation_spec.rb +14 -14
- data/spec/spec_helper.rb +31 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 93a842b5f48d12dcd6e53fe6ffef4ff8bed6ba35
|
4
|
+
data.tar.gz: 2fe79284a9107ababa2758575b61906b2814b9d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f45afa7dde42bc05d0b22cb913ce121b99dd77d20ce2f67e2b7990f3ea0b686cb8c533c4e91a03eb0eb043a00c0bb0953f5e8390e77b945bff319f321136a941
|
7
|
+
data.tar.gz: 12307bd1cb569a0dba41172e052a60667ef27b7c81aacf7f1b2db9df30806d26ab75b717fc9aca10ea4eb740c01d96081dd852ec98d3b539edf29c1ceda75609
|
data/README.md
CHANGED
@@ -495,6 +495,28 @@ class Person < ActiveRestClient::Base
|
|
495
495
|
end
|
496
496
|
```
|
497
497
|
|
498
|
+
### Parallel Requests
|
499
|
+
|
500
|
+
Sometimes you know you will need to make a bunch of requests and you don't want to wait for one to finish to start the next. When using parallel requests there is the potential to finish many requests all at the same time taking only as long as the single longest request. To use parallel requests you will need to set Active-Rest-Client to use a Faraday adapter that supports parallel requests [(such as Typhoeus)](https://github.com/lostisland/faraday/wiki/Parallel-requests).
|
501
|
+
```ruby
|
502
|
+
# Set adapter to Typhoeus to use parallel requests
|
503
|
+
ActiveRestClient::Base.adapter = :typhoeus
|
504
|
+
```
|
505
|
+
|
506
|
+
Now you just need to get ahold of the connection that is going to make the requests by specifying the same host that the models will be using. When inside the `in_parallel` block call request methods as usual and access the results after the `in_parallel` block ends.
|
507
|
+
```ruby
|
508
|
+
ActiveRestClient::ConnectionManager.in_parallel('https://www.example.com') do
|
509
|
+
@person = Person.find(1234)
|
510
|
+
@employers = Employer.all
|
511
|
+
|
512
|
+
puts @person #=> nil
|
513
|
+
puts @employers #=> nil
|
514
|
+
end # The requests are all fired in parallel during this end statement
|
515
|
+
|
516
|
+
puts @person.name #=> "John"
|
517
|
+
puts @employers.size #=> 7
|
518
|
+
```
|
519
|
+
|
498
520
|
### Faking Calls
|
499
521
|
|
500
522
|
There are times when an API hasn't been developed yet, so you want to fake the API call response. To do this, you can simply pass a `fake` option when mapping the call containing the response.
|
data/active_rest_client.gemspec
CHANGED
@@ -30,6 +30,7 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.add_development_dependency 'terminal-notifier-guard'
|
31
31
|
spec.add_development_dependency 'coveralls'
|
32
32
|
spec.add_development_dependency "api-auth", ">= 1.3.1"
|
33
|
+
spec.add_development_dependency 'typhoeus'
|
33
34
|
|
34
35
|
spec.add_runtime_dependency "multi_json"
|
35
36
|
spec.add_runtime_dependency "activesupport"
|
@@ -12,7 +12,7 @@ module ActiveRestClient
|
|
12
12
|
attr_accessor :_headers
|
13
13
|
|
14
14
|
instance_methods.each do |m|
|
15
|
-
next unless %w{display
|
15
|
+
next unless %w{display presence load require hash untrust trust freeze method enable_warnings with_warnings suppress capture silence quietly debugger breakpoint}.map(&:to_sym).include? m
|
16
16
|
undef_method m
|
17
17
|
end
|
18
18
|
|
@@ -52,6 +52,10 @@ module ActiveRestClient
|
|
52
52
|
@dirty_attributes.size > 0
|
53
53
|
end
|
54
54
|
|
55
|
+
def errors
|
56
|
+
@attributes[:errors] || (_errors != {} ? _errors : nil)
|
57
|
+
end
|
58
|
+
|
55
59
|
def self._request(request, method = :get, params = nil)
|
56
60
|
prepare_direct_request(request, method).call(params)
|
57
61
|
end
|
@@ -56,17 +56,18 @@ module ActiveRestClient
|
|
56
56
|
return if result.is_a? Symbol
|
57
57
|
return unless perform_caching
|
58
58
|
return unless !result.respond_to?(:_status) || [200, 304].include?(result._status)
|
59
|
+
headers = response.response_headers
|
59
60
|
|
60
|
-
|
61
|
-
|
61
|
+
headers.keys.select{|h| h.is_a? String}.each do |key|
|
62
|
+
headers[key.downcase.to_sym] = headers[key]
|
62
63
|
end
|
63
64
|
|
64
|
-
if cache_store && (
|
65
|
+
if cache_store && (headers[:etag] || headers[:expires])
|
65
66
|
key = "#{request.class_name}:#{request.original_url}"
|
66
67
|
ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{key} - Writing to cache"
|
67
68
|
cached_response = CachedResponse.new(status:response.status, result:result)
|
68
|
-
cached_response.etag =
|
69
|
-
cached_response.expires = Time.parse(
|
69
|
+
cached_response.etag = headers[:etag] if headers[:etag]
|
70
|
+
cached_response.expires = Time.parse(headers[:expires]) rescue nil if headers[:expires]
|
70
71
|
cache_store.write(key, Marshal.dump(cached_response), {}) if cached_response.etag.present? || cached_response.expires
|
71
72
|
end
|
72
73
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
1
3
|
module ActiveRestClient
|
2
4
|
module Configuration
|
3
5
|
module ClassMethods
|
@@ -36,12 +38,14 @@ module ActiveRestClient
|
|
36
38
|
@username
|
37
39
|
end
|
38
40
|
else
|
41
|
+
value = CGI::escape(value) if value.present? && !value.include?("%")
|
39
42
|
@username = value
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
43
46
|
def username=(value)
|
44
47
|
ActiveRestClient::Logger.info "\033[1;4;32m#{name}\033[0m Username set to be #{value}"
|
48
|
+
value = CGI::escape(value) if value.present? && !value.include?("%")
|
45
49
|
@@username = value
|
46
50
|
end
|
47
51
|
|
@@ -53,12 +57,14 @@ module ActiveRestClient
|
|
53
57
|
@password
|
54
58
|
end
|
55
59
|
else
|
60
|
+
value = CGI::escape(value) if value.present? && !value.include?("%")
|
56
61
|
@password = value
|
57
62
|
end
|
58
63
|
end
|
59
64
|
|
60
65
|
def password=(value)
|
61
66
|
ActiveRestClient::Logger.info "\033[1;4;32m#{name}\033[0m Password set..."
|
67
|
+
value = CGI::escape(value) if value.present? && !value.include?("%")
|
62
68
|
@@password = value
|
63
69
|
end
|
64
70
|
|
@@ -17,5 +17,20 @@ module ActiveRestClient
|
|
17
17
|
Thread.current[:_connections][found] if found
|
18
18
|
end
|
19
19
|
|
20
|
+
def self.in_parallel(base_url)
|
21
|
+
begin
|
22
|
+
require 'typhoeus'
|
23
|
+
require 'typhoeus/adapters/faraday'
|
24
|
+
rescue LoadError
|
25
|
+
raise MissingOptionalLibraryError.new("To call '::ActiveRestClient::ConnectionManager.in_parallel' you must include the gem 'Typhoeus' in your Gemfile.")
|
26
|
+
end
|
27
|
+
session = ConnectionManager.get_connection(base_url).session
|
28
|
+
session.in_parallel do
|
29
|
+
yield
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
20
33
|
end
|
34
|
+
|
35
|
+
class MissingOptionalLibraryError < StandardError ; end
|
21
36
|
end
|
@@ -68,7 +68,7 @@ module ActiveRestClient
|
|
68
68
|
|
69
69
|
def translate(result, options = {})
|
70
70
|
result.headers["content-type"] = "application/hal+json"
|
71
|
-
result = OpenStruct.new(status:result.status,
|
71
|
+
result = FaradayResponseProxy.new(OpenStruct.new(status:result.status, response_headers:result.headers, body:result.body))
|
72
72
|
if result.body.present?
|
73
73
|
result.body = yield MultiJson.load(result.body)
|
74
74
|
end
|
@@ -135,7 +135,7 @@ module ActiveRestClient
|
|
135
135
|
|
136
136
|
def render(body, status=200, content_type="application/javascript", headers={})
|
137
137
|
headers["Content-type"] = content_type
|
138
|
-
OpenStruct.new(body:body, status:status,
|
138
|
+
FaradayResponseProxy.new(OpenStruct.new(body:body, status:status, response_headers:headers, proxied:true))
|
139
139
|
end
|
140
140
|
end
|
141
141
|
|
@@ -143,4 +143,38 @@ module ActiveRestClient
|
|
143
143
|
base.extend(ClassMethods)
|
144
144
|
end
|
145
145
|
end
|
146
|
+
|
147
|
+
# FaradayResponseProxy acts just like a Faraday Response object,
|
148
|
+
# however it always resolves the request immediately regardless of
|
149
|
+
# whether it is inside an in_parallel block or not
|
150
|
+
class FaradayResponseProxy
|
151
|
+
def initialize(response)
|
152
|
+
@response = response
|
153
|
+
end
|
154
|
+
|
155
|
+
def headers
|
156
|
+
@response.response_headers
|
157
|
+
end
|
158
|
+
|
159
|
+
def status
|
160
|
+
@response.status
|
161
|
+
end
|
162
|
+
|
163
|
+
def body
|
164
|
+
@response.body
|
165
|
+
end
|
166
|
+
|
167
|
+
def body=(value)
|
168
|
+
@response.body = value
|
169
|
+
value
|
170
|
+
end
|
171
|
+
|
172
|
+
def on_complete
|
173
|
+
yield(@response)
|
174
|
+
end
|
175
|
+
|
176
|
+
def finished?
|
177
|
+
true
|
178
|
+
end
|
179
|
+
end
|
146
180
|
end
|
@@ -13,6 +13,7 @@ module ActiveRestClient
|
|
13
13
|
@method[:options][:has_one] ||= {}
|
14
14
|
@overriden_name = @method[:options][:overriden_name]
|
15
15
|
@object = object
|
16
|
+
@response_delegate = ActiveRestClient::RequestDelegator.new(nil)
|
16
17
|
@params = params
|
17
18
|
@headers = HeadersList.new
|
18
19
|
end
|
@@ -45,14 +46,6 @@ module ActiveRestClient
|
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
48
|
-
def base_url
|
49
|
-
if object_is_class?
|
50
|
-
@object.base_url
|
51
|
-
else
|
52
|
-
@object.class.base_url
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
49
|
def username
|
57
50
|
if object_is_class?
|
58
51
|
@object.username
|
@@ -123,7 +116,7 @@ module ActiveRestClient
|
|
123
116
|
fake = fake.call(self)
|
124
117
|
end
|
125
118
|
ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Faked response found"
|
126
|
-
return handle_response(OpenStruct.new(status:200, body:fake,
|
119
|
+
return handle_response(OpenStruct.new(status:200, body:fake, response_headers:{"X-ARC-Faked-Response" => "true"}))
|
127
120
|
end
|
128
121
|
if object_is_class?
|
129
122
|
@object.send(:_filter_request, :before, @method[:name], self)
|
@@ -143,24 +136,47 @@ module ActiveRestClient
|
|
143
136
|
etag = cached.etag
|
144
137
|
end
|
145
138
|
end
|
146
|
-
|
147
|
-
|
148
|
-
|
139
|
+
|
140
|
+
response = (
|
141
|
+
if proxy
|
142
|
+
proxy.handle(self) do |request|
|
143
|
+
request.do_request(etag)
|
144
|
+
end
|
145
|
+
else
|
146
|
+
do_request(etag)
|
149
147
|
end
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
148
|
+
)
|
149
|
+
|
150
|
+
# This block is called immediately when this request is not inside a parallel request block.
|
151
|
+
# Otherwise this callback is called after the parallel request block ends.
|
152
|
+
response.on_complete do |response_env|
|
153
|
+
if verbose?
|
154
|
+
ActiveRestClient::Logger.debug " Response"
|
155
|
+
ActiveRestClient::Logger.debug " << Status : #{response_env.status}"
|
156
|
+
response_env.response_headers.each do |k,v|
|
157
|
+
ActiveRestClient::Logger.debug " << #{k} : #{v}"
|
158
|
+
end
|
159
|
+
ActiveRestClient::Logger.debug " << Body:\n#{response_env.body}"
|
160
|
+
end
|
161
|
+
|
162
|
+
if object_is_class? && @object.record_response?
|
163
|
+
@object.record_response(self.url, response_env)
|
164
|
+
end
|
165
|
+
if object_is_class?
|
166
|
+
@object.send(:_filter_request, :after, @method[:name], response_env)
|
167
|
+
else
|
168
|
+
@object.class.send(:_filter_request, :after, @method[:name], response_env)
|
169
|
+
end
|
170
|
+
|
171
|
+
result = handle_response(response_env, cached)
|
172
|
+
@response_delegate.__setobj__(result)
|
173
|
+
original_object_class.write_cached_response(self, response_env, result)
|
160
174
|
end
|
161
|
-
|
162
|
-
|
163
|
-
result
|
175
|
+
|
176
|
+
# If this was not a parallel request just return the original result
|
177
|
+
return result if response.finished?
|
178
|
+
# Otherwise return the delegate which will get set later once the call back is completed
|
179
|
+
return @response_delegate
|
164
180
|
end
|
165
181
|
end
|
166
182
|
|
@@ -277,15 +293,6 @@ module ActiveRestClient
|
|
277
293
|
raise InvalidRequestException.new("Invalid method #{http_method}")
|
278
294
|
end
|
279
295
|
|
280
|
-
if verbose?
|
281
|
-
ActiveRestClient::Logger.debug " Response"
|
282
|
-
ActiveRestClient::Logger.debug " << Status : #{response.status}"
|
283
|
-
response.headers.each do |k,v|
|
284
|
-
ActiveRestClient::Logger.debug " << #{k} : #{v}"
|
285
|
-
end
|
286
|
-
ActiveRestClient::Logger.debug " << Body:\n#{response.body}"
|
287
|
-
end
|
288
|
-
|
289
296
|
response
|
290
297
|
end
|
291
298
|
|
@@ -343,6 +350,8 @@ module ActiveRestClient
|
|
343
350
|
raise HTTPClientException.new(status:status, result:error_response, url:@url)
|
344
351
|
elsif (500..599).include? status
|
345
352
|
raise HTTPServerException.new(status:status, result:error_response, url:@url)
|
353
|
+
elsif status == 0
|
354
|
+
raise TimeoutException.new("Timed out getting #{response.url}")
|
346
355
|
end
|
347
356
|
end
|
348
357
|
|
@@ -359,11 +368,7 @@ module ActiveRestClient
|
|
359
368
|
overriden_name = name
|
360
369
|
object = @method[:options][:has_one][name].new
|
361
370
|
else
|
362
|
-
|
363
|
-
object = @object.new
|
364
|
-
else
|
365
|
-
object = @object.class.new
|
366
|
-
end
|
371
|
+
object = create_object_instance
|
367
372
|
end
|
368
373
|
|
369
374
|
if hal_response? && name.nil?
|
@@ -400,8 +405,8 @@ module ActiveRestClient
|
|
400
405
|
end
|
401
406
|
|
402
407
|
def hal_response?
|
403
|
-
_, content_type = @response.
|
404
|
-
faked_response = @response.
|
408
|
+
_, content_type = @response.response_headers.detect{|k,v| k.downcase == "content-type"}
|
409
|
+
faked_response = @response.response_headers.detect{|k,v| k.downcase == "x-arc-faked-response"}
|
405
410
|
if content_type && content_type.respond_to?(:each)
|
406
411
|
content_type.each do |ct|
|
407
412
|
return true if ct[%r{application\/hal\+json}i]
|
@@ -448,6 +453,10 @@ module ActiveRestClient
|
|
448
453
|
|
449
454
|
private
|
450
455
|
|
456
|
+
def create_object_instance
|
457
|
+
return object_is_class? ? @object.new : @object.class.new
|
458
|
+
end
|
459
|
+
|
451
460
|
def select_name(name, parent_name)
|
452
461
|
if @method[:options][:has_many][name] || @method[:options][:has_one][name]
|
453
462
|
return name
|
@@ -457,7 +466,7 @@ module ActiveRestClient
|
|
457
466
|
end
|
458
467
|
|
459
468
|
def is_json_response?
|
460
|
-
@response.
|
469
|
+
@response.response_headers['Content-Type'].nil? || @response.response_headers['Content-Type'].include?('json')
|
461
470
|
end
|
462
471
|
|
463
472
|
def generate_new_object(options={})
|
@@ -472,15 +481,15 @@ module ActiveRestClient
|
|
472
481
|
body
|
473
482
|
end
|
474
483
|
if body.is_a? Array
|
475
|
-
result = ActiveRestClient::ResultIterator.new(@response
|
484
|
+
result = ActiveRestClient::ResultIterator.new(@response)
|
476
485
|
body.each do |json_object|
|
477
486
|
result << new_object(json_object, @overriden_name)
|
478
487
|
end
|
479
488
|
else
|
480
489
|
result = new_object(body, @overriden_name)
|
481
490
|
result._status = @response.status
|
482
|
-
result._headers = @response.
|
483
|
-
result._etag = @response.
|
491
|
+
result._headers = @response.response_headers
|
492
|
+
result._etag = @response.response_headers['ETag']
|
484
493
|
if !object_is_class? && options[:mutable] != false
|
485
494
|
@object._copy_from(result)
|
486
495
|
@object._clean!
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ActiveRestClient
|
2
|
+
class RequestDelegator < Delegator
|
3
|
+
def initialize(obj)
|
4
|
+
super
|
5
|
+
@delegate_obj = obj
|
6
|
+
end
|
7
|
+
|
8
|
+
def __getobj__
|
9
|
+
@delegate_obj
|
10
|
+
end
|
11
|
+
|
12
|
+
def __setobj__(obj)
|
13
|
+
@delegate_obj = obj
|
14
|
+
end
|
15
|
+
|
16
|
+
def class
|
17
|
+
@delegate_obj.class
|
18
|
+
end
|
19
|
+
|
20
|
+
def method_missing(name, *args, &block)
|
21
|
+
# Handles issue with private method 'test' on base Ruby Object
|
22
|
+
return @delegate_obj.test if name.to_sym == :test
|
23
|
+
|
24
|
+
# Forward request to delegate
|
25
|
+
@delegate_obj.send(name, *args, &block)
|
26
|
+
end
|
27
|
+
|
28
|
+
def kind_of?(obj)
|
29
|
+
@delegate_obj.kind_of?(obj)
|
30
|
+
end
|
31
|
+
|
32
|
+
def is_a?(obj)
|
33
|
+
@delegate_obj.is_a?(obj)
|
34
|
+
end
|
35
|
+
|
36
|
+
def instance_of?(obj)
|
37
|
+
@delegate_obj.instance_of?(obj)
|
38
|
+
end
|
39
|
+
|
40
|
+
def _delegate?
|
41
|
+
return true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -3,10 +3,11 @@ module ActiveRestClient
|
|
3
3
|
include Enumerable
|
4
4
|
|
5
5
|
attr_accessor :_status
|
6
|
-
attr_reader :items
|
6
|
+
attr_reader :items, :_headers
|
7
7
|
|
8
|
-
def initialize(
|
9
|
-
@_status
|
8
|
+
def initialize(response = nil)
|
9
|
+
@_status = response.try :status
|
10
|
+
@_headers = response.try :response_headers
|
10
11
|
@items = []
|
11
12
|
end
|
12
13
|
|
data/lib/active_rest_client.rb
CHANGED
@@ -12,6 +12,7 @@ require "active_rest_client/headers_list"
|
|
12
12
|
require "active_rest_client/lazy_loader"
|
13
13
|
require "active_rest_client/lazy_association_loader"
|
14
14
|
require "active_rest_client/request"
|
15
|
+
require "active_rest_client/request_delegator"
|
15
16
|
require "active_rest_client/validation"
|
16
17
|
require "active_rest_client/request_filtering"
|
17
18
|
require "active_rest_client/proxy_base"
|
data/spec/lib/base_spec.rb
CHANGED
@@ -156,14 +156,14 @@ describe ActiveRestClient::Base do
|
|
156
156
|
end
|
157
157
|
|
158
158
|
it "should be able to lazy instantiate an object from a prefixed lazy_ method call" do
|
159
|
-
expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with('/find/1', anything).and_return(OpenStruct.new(status:200,
|
159
|
+
expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with('/find/1', anything).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
|
160
160
|
example = AlteringClientExample.lazy_find(1)
|
161
161
|
expect(example).to be_an_instance_of(ActiveRestClient::LazyLoader)
|
162
162
|
expect(example.first_name).to eq("Billy")
|
163
163
|
end
|
164
164
|
|
165
165
|
it "should be able to lazy instantiate an object from a prefixed lazy_ method call from an instance" do
|
166
|
-
expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with('/find/1', anything).and_return(OpenStruct.new(status:200,
|
166
|
+
expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with('/find/1', anything).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
|
167
167
|
example = AlteringClientExample.new.lazy_find(1)
|
168
168
|
expect(example).to be_an_instance_of(ActiveRestClient::LazyLoader)
|
169
169
|
expect(example.first_name).to eq("Billy")
|
@@ -246,49 +246,65 @@ describe ActiveRestClient::Base do
|
|
246
246
|
|
247
247
|
context "directly call a URL, rather than via a mapped method" do
|
248
248
|
it "should be able to directly call a URL" do
|
249
|
-
expect_any_instance_of(ActiveRestClient::Request).to receive(:do_request).with(any_args).and_return(OpenStruct.new(status:200,
|
249
|
+
expect_any_instance_of(ActiveRestClient::Request).to receive(:do_request).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
|
250
250
|
EmptyExample._request("http://api.example.com/")
|
251
251
|
end
|
252
252
|
|
253
253
|
it "runs filters as usual" do
|
254
|
-
expect_any_instance_of(ActiveRestClient::Request).to receive(:do_request).with(any_args).and_return(OpenStruct.new(status:200,
|
254
|
+
expect_any_instance_of(ActiveRestClient::Request).to receive(:do_request).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
|
255
255
|
expect(EmptyExample).to receive(:_filter_request).with(any_args).exactly(2).times
|
256
256
|
EmptyExample._request("http://api.example.com/")
|
257
257
|
end
|
258
258
|
|
259
259
|
it "should make an HTTP request" do
|
260
|
-
expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with(any_args).and_return(OpenStruct.new(status:200,
|
260
|
+
expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
|
261
261
|
EmptyExample._request("http://api.example.com/")
|
262
262
|
end
|
263
263
|
|
264
264
|
it "should make an HTTP request including the path in the base_url" do
|
265
|
-
expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with('/v1/all', anything).and_return(OpenStruct.new(status:200,
|
265
|
+
expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with('/v1/all', anything).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
|
266
266
|
NonHostnameBaseUrlExample.all
|
267
267
|
end
|
268
268
|
|
269
269
|
it "should map the response from the directly called URL in the normal way" do
|
270
|
-
expect_any_instance_of(ActiveRestClient::Request).to receive(:do_request).with(any_args).and_return(OpenStruct.new(status:200,
|
270
|
+
expect_any_instance_of(ActiveRestClient::Request).to receive(:do_request).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
|
271
271
|
example = EmptyExample._request("http://api.example.com/")
|
272
272
|
expect(example.first_name).to eq("Billy")
|
273
273
|
end
|
274
274
|
|
275
275
|
it "should be able to pass the plain response from the directly called URL bypassing JSON loading" do
|
276
|
-
|
277
|
-
expect_any_instance_of(ActiveRestClient::Connection).to receive(:post).with(any_args).and_return(OpenStruct.new(status:200,
|
278
|
-
expect(EmptyExample._plain_request("http://api.example.com/", :post, {id:1234})).to eq(
|
276
|
+
response_body = "This is another non-JSON string"
|
277
|
+
expect_any_instance_of(ActiveRestClient::Connection).to receive(:post).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:response_body)))
|
278
|
+
expect(EmptyExample._plain_request("http://api.example.com/", :post, {id:1234})).to eq(response_body)
|
279
|
+
end
|
280
|
+
|
281
|
+
context "Simulating Faraday connection in_parallel" do
|
282
|
+
it "should be able to pass the plain response from the directly called URL bypassing JSON loading" do
|
283
|
+
response_body = "This is another non-JSON string"
|
284
|
+
response = ::FaradayResponseMock.new(
|
285
|
+
OpenStruct.new(status:200, response_headers:{}, body:response_body),
|
286
|
+
false)
|
287
|
+
expect_any_instance_of(ActiveRestClient::Connection).to receive(:post).with(any_args).and_return(response)
|
288
|
+
result = EmptyExample._plain_request("http://api.example.com/", :post, {id:1234})
|
289
|
+
|
290
|
+
expect(result).to eq(nil)
|
291
|
+
|
292
|
+
response.finish
|
293
|
+
expect(result).to eq(response_body)
|
294
|
+
end
|
279
295
|
end
|
280
296
|
|
281
297
|
it "should cache plain requests separately" do
|
282
298
|
perform_caching = EmptyExample.perform_caching
|
283
299
|
cache_store = EmptyExample.cache_store
|
284
300
|
begin
|
285
|
-
response =
|
286
|
-
other_response =
|
301
|
+
response = "This is a non-JSON string"
|
302
|
+
other_response = "This is another non-JSON string"
|
287
303
|
allow_any_instance_of(ActiveRestClient::Connection).to receive(:get) do |instance, url, others|
|
288
304
|
if url == "/?test=1"
|
289
|
-
OpenStruct.new(status:200,
|
305
|
+
::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:response))
|
290
306
|
else
|
291
|
-
OpenStruct.new(status:200,
|
307
|
+
::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:other_response))
|
292
308
|
end
|
293
309
|
end
|
294
310
|
EmptyExample.perform_caching = true
|
@@ -302,19 +318,19 @@ describe ActiveRestClient::Base do
|
|
302
318
|
end
|
303
319
|
|
304
320
|
it "should be able to lazy load a direct URL request" do
|
305
|
-
expect_any_instance_of(ActiveRestClient::Request).to receive(:do_request).with(any_args).and_return(OpenStruct.new(status:200,
|
321
|
+
expect_any_instance_of(ActiveRestClient::Request).to receive(:do_request).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
|
306
322
|
example = EmptyExample._lazy_request("http://api.example.com/")
|
307
323
|
expect(example).to be_an_instance_of(ActiveRestClient::LazyLoader)
|
308
324
|
expect(example.first_name).to eq("Billy")
|
309
325
|
end
|
310
326
|
|
311
327
|
it "should be able to specify a method and parameters for the call" do
|
312
|
-
expect_any_instance_of(ActiveRestClient::Connection).to receive(:post).with(any_args).and_return(OpenStruct.new(status:200,
|
328
|
+
expect_any_instance_of(ActiveRestClient::Connection).to receive(:post).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
|
313
329
|
EmptyExample._request("http://api.example.com/", :post, {id:1234})
|
314
330
|
end
|
315
331
|
|
316
332
|
it "should be able to use mapped methods to create a request to pass in to _lazy_request" do
|
317
|
-
expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with('/find/1', anything).and_return(OpenStruct.new(status:200,
|
333
|
+
expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with('/find/1', anything).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"{\"first_name\":\"Billy\"}")))
|
318
334
|
request = AlteringClientExample._request_for(:find, :id => 1)
|
319
335
|
example = AlteringClientExample._lazy_request(request)
|
320
336
|
expect(example.first_name).to eq("Billy")
|
@@ -323,7 +339,7 @@ describe ActiveRestClient::Base do
|
|
323
339
|
|
324
340
|
context "Recording a response" do
|
325
341
|
it "calls back to the record_response callback with the url and response body" do
|
326
|
-
expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with(any_args).and_return(OpenStruct.new(status:200,
|
342
|
+
expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:"Hello world")))
|
327
343
|
expect{RecordResponseExample.all}.to raise_error(Exception, "/all|Hello world")
|
328
344
|
end
|
329
345
|
end
|
data/spec/lib/caching_spec.rb
CHANGED
@@ -111,7 +111,7 @@ describe ActiveRestClient::Caching do
|
|
111
111
|
result:@cached_object,
|
112
112
|
etag:@etag)
|
113
113
|
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(Marshal.dump(cached_response))
|
114
|
-
expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with("/", hash_including("If-None-Match" => @etag)).and_return(OpenStruct.new(status:304,
|
114
|
+
expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with("/", hash_including("If-None-Match" => @etag)).and_return(::FaradayResponseMock.new(OpenStruct.new(status:304, response_headers:{})))
|
115
115
|
ret = Person.all
|
116
116
|
expect(ret.first_name).to eq("Johnny")
|
117
117
|
end
|
@@ -125,7 +125,7 @@ describe ActiveRestClient::Caching do
|
|
125
125
|
allow_any_instance_of(CachingExampleCacheStore5).to receive(:read).and_return(Marshal.dump(cached_response))
|
126
126
|
new_name = 'Pete'
|
127
127
|
response_body = Person.new(first_name: new_name).to_json
|
128
|
-
response = double(status: 200,
|
128
|
+
response = ::FaradayResponseMock.new(double(status: 200, response_headers: {}, body: response_body))
|
129
129
|
allow_any_instance_of(ActiveRestClient::Connection).to(
|
130
130
|
receive(:get).with('/', hash_including('If-None-Match' => @etag)).and_return(response))
|
131
131
|
|
@@ -159,7 +159,7 @@ describe ActiveRestClient::Caching do
|
|
159
159
|
|
160
160
|
it "should restore a result iterator from the cache store, if there's a hard expiry" do
|
161
161
|
class CachingExample3 < ActiveRestClient::Base ; end
|
162
|
-
object = ActiveRestClient::ResultIterator.new(200)
|
162
|
+
object = ActiveRestClient::ResultIterator.new(double(status: 200))
|
163
163
|
object << CachingExample3.new(first_name:"Johnny")
|
164
164
|
object << CachingExample3.new(first_name:"Billy")
|
165
165
|
etag = "6527914a91e0c5769f6de281f25bd891"
|
@@ -185,7 +185,7 @@ describe ActiveRestClient::Caching do
|
|
185
185
|
it "should write the response to the cache if there's an etag" do
|
186
186
|
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(nil)
|
187
187
|
expect_any_instance_of(CachingExampleCacheStore5).to receive(:write).once.with("Person:/", an_instance_of(String), {})
|
188
|
-
expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with("/", an_instance_of(Hash)).and_return(OpenStruct.new(status:200, body:"{\"result\":true}",
|
188
|
+
expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with("/", an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, body:"{\"result\":true}", response_headers:{etag:"1234567890"})))
|
189
189
|
Person.perform_caching true
|
190
190
|
ret = Person.all
|
191
191
|
end
|
@@ -193,7 +193,7 @@ describe ActiveRestClient::Caching do
|
|
193
193
|
it "should write the response to the cache if there's a hard expiry" do
|
194
194
|
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(nil)
|
195
195
|
expect_any_instance_of(CachingExampleCacheStore5).to receive(:write).once.with("Person:/", an_instance_of(String), an_instance_of(Hash))
|
196
|
-
expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with("/", an_instance_of(Hash)).and_return(OpenStruct.new(status:200, body:"{\"result\":true}",
|
196
|
+
expect_any_instance_of(ActiveRestClient::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})))
|
197
197
|
Person.perform_caching = true
|
198
198
|
ret = Person.all
|
199
199
|
end
|