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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 77e442c1fd4bf22c3ef98a18bb9f67d034d13dcb
4
- data.tar.gz: eb7c6b99213a31eb56f69c276642fe03825e3a9d
3
+ metadata.gz: 93a842b5f48d12dcd6e53fe6ffef4ff8bed6ba35
4
+ data.tar.gz: 2fe79284a9107ababa2758575b61906b2814b9d1
5
5
  SHA512:
6
- metadata.gz: f21a5d8fad3841c0891d4a619d59b6bdaf0f5f920c4512cf3be1b9eb72b9d8f7d2ac1acff05ce62a3aef9cbb17661c5f1ebedd13943863c149b4b63ad3ba7e47
7
- data.tar.gz: 7ed888f35736130ffc40118dbde8ec51f764d13f38cb48fcc5b71337b4fbd2a45a0cd77aee19ea96d6135f3c66393272406391a7924cc7338771a2562e3eef73
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.
@@ -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 errors presence load require hash untrust trust freeze method enable_warnings with_warnings suppress capture silence quietly debugger breakpoint}.map(&:to_sym).include? m
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
- response.headers.keys.select{|h| h.is_a? String}.each do |key|
61
- response.headers[key.downcase.to_sym] = response.headers[key]
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 && (response.headers[:etag] || response.headers[:expires])
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 = response.headers[:etag] if response.headers[:etag]
69
- cached_response.expires = Time.parse(response.headers[:expires]) rescue nil if response.headers[:expires]
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, headers:result.headers, body:result.body)
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, headers:headers, proxied:true)
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, headers:{"X-ARC-Faked-Response" => "true"}))
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
- response = if proxy
147
- proxy.handle(self) do |request|
148
- request.do_request(etag)
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
- else
151
- do_request(etag)
152
- end
153
- if object_is_class? && @object.record_response?
154
- @object.record_response(self.url, response)
155
- end
156
- if object_is_class?
157
- @object.send(:_filter_request, :after, @method[:name], response)
158
- else
159
- @object.class.send(:_filter_request, :after, @method[:name], response)
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
- result = handle_response(response, cached)
162
- original_object_class.write_cached_response(self, response, result)
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
- if object_is_class?
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.headers.detect{|k,v| k.downcase == "content-type"}
404
- faked_response = @response.headers.detect{|k,v| k.downcase == "x-arc-faked-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.headers['Content-Type'].nil? || @response.headers['Content-Type'].include?('json')
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.status)
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.headers
483
- result._etag = @response.headers['ETag']
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(status = nil)
9
- @_status = 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
 
@@ -51,7 +51,7 @@ module ActiveRestClient
51
51
  @errors.empty?
52
52
  end
53
53
 
54
- def errors
54
+ def _errors
55
55
  @errors ||= Hash.new {|h,k| h[k] = []}
56
56
  @errors
57
57
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveRestClient
2
- VERSION = "1.0.9"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -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"
@@ -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, headers:{}, body:"{\"first_name\":\"Billy\"}"))
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, headers:{}, body:"{\"first_name\":\"Billy\"}"))
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, headers:{}, body:"{\"first_name\":\"Billy\"}"))
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, headers:{}, body:"{\"first_name\":\"Billy\"}"))
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, headers:{}, body:"{\"first_name\":\"Billy\"}"))
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, headers:{}, body:"{\"first_name\":\"Billy\"}"))
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, headers:{}, body:"{\"first_name\":\"Billy\"}"))
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
- response = OpenStruct.new(_status:200, body:"This is another non-JSON string")
277
- expect_any_instance_of(ActiveRestClient::Connection).to receive(:post).with(any_args).and_return(OpenStruct.new(status:200, headers:{}, body:response))
278
- expect(EmptyExample._plain_request("http://api.example.com/", :post, {id:1234})).to eq(response)
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 = OpenStruct.new(_status:200, body:"This is a non-JSON string")
286
- other_response = OpenStruct.new(_status:200, body:"This is another non-JSON string")
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, headers:{}, body:response)
305
+ ::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{}, body:response))
290
306
  else
291
- OpenStruct.new(status:200, headers:{}, body:other_response)
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, headers:{}, body:"{\"first_name\":\"Billy\"}"))
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, headers:{}, body:"{\"first_name\":\"Billy\"}"))
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, headers:{}, body:"{\"first_name\":\"Billy\"}"))
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, headers:{}, body:"Hello world"))
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
@@ -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, headers:{}))
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, headers: {}, body: response_body)
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}", headers:{etag:"1234567890"}))
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}", headers:{expires:(Time.now + 30).rfc822}))
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