active_rest_client 0.9.75 → 1.0.0

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.
Binary file
@@ -46,7 +46,7 @@ module ActiveRestClient
46
46
  def read_cached_response(request)
47
47
  if cache_store && perform_caching
48
48
  key = "#{request.class_name}:#{request.original_url}"
49
- ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{key} - Reading from cache"
49
+ ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{key} - Trying to read from cache"
50
50
  value = cache_store.read(key)
51
51
  value = Marshal.load(value) rescue value
52
52
  end
@@ -17,6 +17,10 @@ module ActiveRestClient
17
17
  _map_call(name, url:url, method: :delete, options:options)
18
18
  end
19
19
 
20
+ def patch(name, url, options = {})
21
+ _map_call(name, url:url, method: :patch, options:options)
22
+ end
23
+
20
24
  def _map_call(name, details)
21
25
  _calls[name] = {name:name}.merge(details)
22
26
  _calls["lazy_#{name}".to_sym] = {name:name}.merge(details)
@@ -114,6 +114,11 @@ module ActiveRestClient
114
114
  elsif cached.etag.to_s != "" #present? isn't working for some reason
115
115
  ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Etag cached copy found with etag #{cached.etag}"
116
116
  etag = cached.etag
117
+ response = do_request(etag)
118
+ if response.status == 304
119
+ ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Response status 304. Copy is still fresh"
120
+ return handle_cached_response(cached)
121
+ end
117
122
  end
118
123
  end
119
124
  response = if proxy
@@ -224,11 +229,12 @@ module ActiveRestClient
224
229
 
225
230
  if verbose?
226
231
  ActiveRestClient::Logger.debug "ActiveRestClient Verbose Log:"
227
- ActiveRestClient::Logger.debug " > GET #{@url} HTTP/1.1"
232
+ ActiveRestClient::Logger.debug " Request"
233
+ ActiveRestClient::Logger.debug " >> GET #{@url} HTTP/1.1"
228
234
  http_headers.each do |k,v|
229
- ActiveRestClient::Logger.debug " > #{k} : #{v}"
235
+ ActiveRestClient::Logger.debug " >> #{k} : #{v}"
230
236
  end
231
- ActiveRestClient::Logger.debug " > #{@body}"
237
+ ActiveRestClient::Logger.debug " >> Body:\n#{@body}"
232
238
  end
233
239
 
234
240
  case http_method
@@ -245,10 +251,12 @@ module ActiveRestClient
245
251
  end
246
252
 
247
253
  if verbose?
254
+ ActiveRestClient::Logger.debug " Response"
255
+ ActiveRestClient::Logger.debug " << Status : #{response.status}"
248
256
  response.headers.each do |k,v|
249
- ActiveRestClient::Logger.debug " < #{k} : #{v}"
257
+ ActiveRestClient::Logger.debug " << #{k} : #{v}"
250
258
  end
251
- ActiveRestClient::Logger.debug " < #{response.body}"
259
+ ActiveRestClient::Logger.debug " << Body:\n#{response.body}"
252
260
  end
253
261
 
254
262
  response
@@ -268,62 +276,49 @@ module ActiveRestClient
268
276
  end
269
277
 
270
278
  def handle_response(response)
271
- if response.status == 304
272
- ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Etag copy is the same as the server"
273
- return :not_modified
274
- end
275
- if response.respond_to?(:proxied) && response.proxied
276
- ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Response was proxied, unable to determine size"
277
- else
278
- ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Response received #{response.body.size} bytes"
279
- end
280
-
281
- if @method[:options][:plain]
282
- return @response = response.body
283
- end
284
-
285
279
  @response = response
280
+ @response.status ||= 200
286
281
 
287
- if response.body.is_a?(Array) || response.body.is_a?(Hash)
288
- body = response.body
289
- else
290
- body = MultiJson.load(response.body) || {}
291
- end
292
- body = begin
293
- @method[:name].nil? ? body : translator.send(@method[:name], body)
294
- rescue NoMethodError
295
- body
296
- end
297
- if body.is_a? Array
298
- result = ActiveRestClient::ResultIterator.new(response.status)
299
- body.each do |json_object|
300
- result << new_object(json_object, @overriden_name)
282
+ if (200..399).include? @response.status
283
+ if response.status == 304
284
+ ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Etag copy is the same as the server"
285
+ return :not_modified
286
+ end
287
+ if @method[:options][:plain]
288
+ return @response = response.body
289
+ elsif is_json_response?
290
+ if @response.respond_to?(:proxied) && @response.proxied
291
+ ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Response was proxied, unable to determine size"
292
+ else
293
+ ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Response received #{@response.body.size} bytes"
294
+ end
295
+ result = generate_new_object
296
+ else
297
+ raise ResponseParseException.new(status:@response.status, body:@response.body)
301
298
  end
302
299
  else
303
- result = new_object(body, @overriden_name)
304
- result._status = response.status
305
- unless object_is_class?
306
- @object._copy_from(result)
307
- result = @object
300
+ if is_json_response?
301
+ error_response = generate_new_object(mutable: false)
302
+ else
303
+ error_response = @response.body
304
+ end
305
+ if @response.status == 400
306
+ raise HTTPBadRequestClientException.new(status:@response.status, result:error_response, url:@url)
307
+ elsif @response.status == 401
308
+ raise HTTPUnauthorisedClientException.new(status:@response.status, result:error_response, url:@url)
309
+ elsif @response.status == 403
310
+ raise HTTPForbiddenClientException.new(status:@response.status, result:error_response, url:@url)
311
+ elsif @response.status == 404
312
+ raise HTTPNotFoundClientException.new(status:@response.status, result:error_response, url:@url)
313
+ elsif (400..499).include? @response.status
314
+ raise HTTPClientException.new(status:@response.status, result:error_response, url:@url)
315
+ elsif (500..599).include? @response.status
316
+ raise HTTPServerException.new(status:@response.status, result:error_response, url:@url)
308
317
  end
309
318
  end
310
319
 
311
- response.status ||= 200
312
- if response.status == 401
313
- raise HTTPUnauthorisedClientException.new(status:response.status, result:result, url:@url)
314
- elsif response.status == 403
315
- raise HTTPForbiddenClientException.new(status:response.status, result:result, url:@url)
316
- elsif response.status == 404
317
- raise HTTPNotFoundClientException.new(status:response.status, result:result, url:@url)
318
- elsif (400..499).include? response.status
319
- raise HTTPClientException.new(status:response.status, result:result, url:@url)
320
- elsif (500..599).include? response.status
321
- raise HTTPServerException.new(status:response.status, result:result, url:@url)
322
- end
323
320
 
324
321
  result
325
- rescue MultiJson::ParseError
326
- raise ResponseParseException.new(status:response.status, body:response.body)
327
322
  end
328
323
 
329
324
  def new_object(attributes, name = nil)
@@ -418,6 +413,39 @@ module ActiveRestClient
418
413
 
419
414
  attributes
420
415
  end
416
+
417
+ private
418
+
419
+ def is_json_response?
420
+ @response.headers['Content-Type'].nil? || @response.headers['Content-Type'].include?('json')
421
+ end
422
+
423
+ def generate_new_object(options={})
424
+ if @response.body.is_a?(Array) || @response.body.is_a?(Hash)
425
+ body = @response.body
426
+ else
427
+ body = MultiJson.load(@response.body) || {}
428
+ end
429
+ body = begin
430
+ @method[:name].nil? ? body : translator.send(@method[:name], body)
431
+ rescue NoMethodError
432
+ body
433
+ end
434
+ if body.is_a? Array
435
+ result = ActiveRestClient::ResultIterator.new(@response.status)
436
+ body.each do |json_object|
437
+ result << new_object(json_object, @overriden_name)
438
+ end
439
+ else
440
+ result = new_object(body, @overriden_name)
441
+ result._status = @response.status
442
+ if !object_is_class? && options[:mutable] != false
443
+ @object._copy_from(result)
444
+ result = @object
445
+ end
446
+ end
447
+ result
448
+ end
421
449
  end
422
450
 
423
451
  class RequestException < StandardError ; end
@@ -441,6 +469,7 @@ module ActiveRestClient
441
469
  end
442
470
  class HTTPClientException < HTTPException ; end
443
471
  class HTTPUnauthorisedClientException < HTTPClientException ; end
472
+ class HTTPBadRequestClientException < HTTPClientException ; end
444
473
  class HTTPForbiddenClientException < HTTPClientException ; end
445
474
  class HTTPNotFoundClientException < HTTPClientException ; end
446
475
  class HTTPServerException < HTTPException ; end
@@ -1,3 +1,3 @@
1
1
  module ActiveRestClient
2
- VERSION = "0.9.75"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -8,7 +8,8 @@ class MappingExample < MappingExampleBase
8
8
  get :test_get, "/get", tag:1, fake:"{result:true}", lazy:[:something]
9
9
  put :test_put, "/put", tag:2
10
10
  post :test_post, "/post", tag:3
11
- delete :test_delete, "/delete", tag:4
11
+ patch :test_patch, "/patch", tag:4
12
+ delete :test_delete, "/delete", tag:5
12
13
  end
13
14
 
14
15
  describe ActiveRestClient::Mapping do
@@ -23,6 +24,7 @@ describe ActiveRestClient::Mapping do
23
24
  expect(MappingExample._calls[:test_get][:url]).to eq("/get")
24
25
  expect(MappingExample._calls[:test_put][:url]).to eq("/put")
25
26
  expect(MappingExample._calls[:test_post][:url]).to eq("/post")
27
+ expect(MappingExample._calls[:test_patch][:url]).to eq("/patch")
26
28
  expect(MappingExample._calls[:test_delete][:url]).to eq("/delete")
27
29
  end
28
30
 
@@ -30,6 +32,7 @@ describe ActiveRestClient::Mapping do
30
32
  expect(MappingExample._calls[:test_get][:method]).to eq(:get)
31
33
  expect(MappingExample._calls[:test_put][:method]).to eq(:put)
32
34
  expect(MappingExample._calls[:test_post][:method]).to eq(:post)
35
+ expect(MappingExample._calls[:test_patch][:method]).to eq(:patch)
33
36
  expect(MappingExample._calls[:test_delete][:method]).to eq(:delete)
34
37
  end
35
38
 
@@ -39,7 +42,8 @@ describe ActiveRestClient::Mapping do
39
42
  expect(MappingExample._calls[:test_get][:options][:tag]).to eq(1)
40
43
  expect(MappingExample._calls[:test_put][:options][:tag]).to eq(2)
41
44
  expect(MappingExample._calls[:test_post][:options][:tag]).to eq(3)
42
- expect(MappingExample._calls[:test_delete][:options][:tag]).to eq(4)
45
+ expect(MappingExample._calls[:test_patch][:options][:tag]).to eq(4)
46
+ expect(MappingExample._calls[:test_delete][:options][:tag]).to eq(5)
43
47
  end
44
48
 
45
49
  it "should allow for mapped calls on the class" do
@@ -233,8 +233,8 @@ describe ActiveRestClient::Request do
233
233
  ActiveRestClient::ConnectionManager.should_receive(:get_connection).and_return(connection)
234
234
  connection.should_receive(:get).with("/all", an_instance_of(Hash)).and_return(OpenStruct.new(body:'{"result":true}', headers:{"Content-Type" => "application/json", "Connection" => "close"}))
235
235
  ActiveRestClient::Logger.should_receive(:debug).with("ActiveRestClient Verbose Log:")
236
- ActiveRestClient::Logger.should_receive(:debug).with(/ > /).at_least(:twice)
237
- ActiveRestClient::Logger.should_receive(:debug).with(/ < /).at_least(:twice)
236
+ ActiveRestClient::Logger.should_receive(:debug).with(/ >> /).at_least(:twice)
237
+ ActiveRestClient::Logger.should_receive(:debug).with(/ << /).at_least(:twice)
238
238
  ActiveRestClient::Logger.stub(:debug).with(any_args)
239
239
  VerboseExampleClient.all
240
240
  end
@@ -270,7 +270,7 @@ describe ActiveRestClient::Request do
270
270
  end
271
271
  expect(e).to be_instance_of(ActiveRestClient::HTTPForbiddenClientException)
272
272
  expect(e.status).to eq(403)
273
- expect(e.result.first_name).to eq("John")
273
+ expect(e.result.first_name).to eq("John")
274
274
  end
275
275
 
276
276
  it "should raise a not found client exception for 404 errors" do
@@ -304,7 +304,7 @@ describe ActiveRestClient::Request do
304
304
  end
305
305
  expect(e).to be_instance_of(ActiveRestClient::HTTPClientException)
306
306
  expect(e.status).to eq(409)
307
- expect(e.result.first_name).to eq("John")
307
+ expect(e.result.first_name).to eq("John")
308
308
  end
309
309
 
310
310
  it "should raise a server exception for 5xx errors" do
@@ -330,25 +330,79 @@ describe ActiveRestClient::Request do
330
330
  any_instance.
331
331
  should_receive(:post).
332
332
  with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
333
- and_return(OpenStruct.new(body:error_content, headers:{}, status:500))
333
+ and_return(OpenStruct.new(body:error_content, headers:{'Content-Type' => 'text/html'}, status:500))
334
334
  object = ExampleClient.new(first_name:"John", should_disappear:true)
335
335
  begin
336
336
  object.create
337
- rescue ActiveRestClient::ResponseParseException => e
337
+ rescue => e
338
338
  e
339
339
  end
340
- expect(e).to be_instance_of(ActiveRestClient::ResponseParseException)
340
+ expect(e).to be_instance_of(ActiveRestClient::HTTPServerException)
341
341
  expect(e.status).to eq(500)
342
+ expect(e.result).to eq(error_content)
343
+ end
344
+
345
+ it "should raise a bad request exception for 400 response status" do
346
+ error_content = "<h1>400 Bad Request</h1>"
347
+ ActiveRestClient::Connection.
348
+ any_instance.
349
+ should_receive(:post).
350
+ with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
351
+ and_return(OpenStruct.new(body:error_content, headers:{'Content-Type' => 'text/html'}, status:400))
352
+ object = ExampleClient.new(first_name:"John", should_disappear:true)
353
+ begin
354
+ object.create
355
+ rescue => e
356
+ e
357
+ end
358
+ expect(e).to be_instance_of(ActiveRestClient::HTTPBadRequestClientException)
359
+ expect(e.status).to eq(400)
360
+ expect(e.result).to eq(error_content)
361
+ end
362
+
363
+ it "should raise response parse exception for 200 response status and non json content type" do
364
+ error_content = "<h1>malformed json</h1>"
365
+ ActiveRestClient::Connection.
366
+ any_instance.
367
+ should_receive(:post).
368
+ with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
369
+ and_return(OpenStruct.new(body:error_content, headers:{'Content-Type' => 'text/html'}, status:200))
370
+ object = ExampleClient.new(first_name:"John", should_disappear:true)
371
+ begin
372
+ object.create
373
+ rescue => e
374
+ e
375
+ end
376
+ expect(e).to be_instance_of(ActiveRestClient::ResponseParseException)
377
+ expect(e.status).to eq(200)
342
378
  expect(e.body).to eq(error_content)
343
379
  end
344
380
 
381
+ it "should not override the attributes of the existing object on error response status" do
382
+ ActiveRestClient::Connection.
383
+ any_instance.
384
+ should_receive(:post).
385
+ with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
386
+ and_return(OpenStruct.new(body:'{"errors": ["validation": "error in validation"]}', headers:{'Content-Type' => 'text/html'}, status:400))
387
+ object = ExampleClient.new(first_name:"John", should_disappear:true)
388
+ begin
389
+ object.create
390
+ rescue => e
391
+ e
392
+ end
393
+ expect(e).to be_instance_of(ActiveRestClient::HTTPBadRequestClientException)
394
+ expect(e.status).to eq(400)
395
+ expect(object.first_name).to eq 'John'
396
+ expect(object.errors).to be_nil
397
+ end
398
+
345
399
  it "should raise an exception if you try to pass in an unsupport method" do
346
400
  method = {:method => :wiggle, url:"/"}
347
401
  class RequestFakeObject
348
402
  def request_body_type
349
403
  :form_encoded
350
404
  end
351
-
405
+
352
406
  def base_url
353
407
  "http://www.example.com/"
354
408
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_rest_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.75
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Which Ltd
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-21 00:00:00.000000000 Z
12
+ date: 2014-04-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -219,12 +219,15 @@ files:
219
219
  - ".rspec"
220
220
  - ".simplecov"
221
221
  - ".travis.yml"
222
+ - CONTRIBUTING.md
222
223
  - Gemfile
223
224
  - Guardfile
224
225
  - LICENSE.txt
225
226
  - README.md
226
227
  - Rakefile
227
228
  - active_rest_client.gemspec
229
+ - doc/ActiveRestClient Internals.graffle
230
+ - doc/ActiveRestClient Internals.png
228
231
  - lib/active_rest_client.rb
229
232
  - lib/active_rest_client/base.rb
230
233
  - lib/active_rest_client/caching.rb
@@ -282,7 +285,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
282
285
  version: '0'
283
286
  requirements: []
284
287
  rubyforge_project:
285
- rubygems_version: 2.2.0
288
+ rubygems_version: 2.2.2
286
289
  signing_key:
287
290
  specification_version: 4
288
291
  summary: This gem is for accessing REST services in an ActiveRecord style. ActiveResource