acfs 1.3.2 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -0
  3. data/README.md +10 -23
  4. data/acfs.gemspec +19 -20
  5. data/lib/acfs.rb +2 -0
  6. data/lib/acfs/adapter/base.rb +6 -8
  7. data/lib/acfs/adapter/typhoeus.rb +25 -6
  8. data/lib/acfs/collection.rb +2 -1
  9. data/lib/acfs/collections/paginatable.rb +4 -3
  10. data/lib/acfs/configuration.rb +14 -7
  11. data/lib/acfs/errors.rb +60 -19
  12. data/lib/acfs/global.rb +2 -0
  13. data/lib/acfs/location.rb +9 -5
  14. data/lib/acfs/middleware/base.rb +5 -1
  15. data/lib/acfs/middleware/json.rb +6 -2
  16. data/lib/acfs/middleware/logger.rb +2 -0
  17. data/lib/acfs/middleware/msgpack.rb +2 -0
  18. data/lib/acfs/middleware/print.rb +2 -0
  19. data/lib/acfs/middleware/serializer.rb +2 -0
  20. data/lib/acfs/operation.rb +20 -3
  21. data/lib/acfs/request.rb +5 -1
  22. data/lib/acfs/request/callbacks.rb +5 -1
  23. data/lib/acfs/resource.rb +2 -0
  24. data/lib/acfs/resource/attributes.rb +7 -4
  25. data/lib/acfs/resource/attributes/base.rb +2 -1
  26. data/lib/acfs/resource/attributes/boolean.rb +2 -0
  27. data/lib/acfs/resource/attributes/date_time.rb +3 -2
  28. data/lib/acfs/resource/attributes/dict.rb +2 -0
  29. data/lib/acfs/resource/attributes/float.rb +5 -3
  30. data/lib/acfs/resource/attributes/integer.rb +2 -0
  31. data/lib/acfs/resource/attributes/list.rb +2 -0
  32. data/lib/acfs/resource/attributes/string.rb +2 -0
  33. data/lib/acfs/resource/attributes/uuid.rb +4 -3
  34. data/lib/acfs/resource/dirty.rb +2 -0
  35. data/lib/acfs/resource/initialization.rb +2 -0
  36. data/lib/acfs/resource/loadable.rb +2 -0
  37. data/lib/acfs/resource/locatable.rb +10 -6
  38. data/lib/acfs/resource/operational.rb +2 -1
  39. data/lib/acfs/resource/persistence.rb +7 -6
  40. data/lib/acfs/resource/query_methods.rb +6 -4
  41. data/lib/acfs/resource/service.rb +3 -1
  42. data/lib/acfs/resource/validation.rb +19 -7
  43. data/lib/acfs/response.rb +2 -0
  44. data/lib/acfs/response/formats.rb +2 -0
  45. data/lib/acfs/response/status.rb +3 -1
  46. data/lib/acfs/rspec.rb +2 -0
  47. data/lib/acfs/runner.rb +6 -1
  48. data/lib/acfs/service.rb +24 -13
  49. data/lib/acfs/service/middleware.rb +2 -0
  50. data/lib/acfs/service/middleware/stack.rb +5 -3
  51. data/lib/acfs/singleton_resource.rb +4 -2
  52. data/lib/acfs/stub.rb +32 -11
  53. data/lib/acfs/util.rb +2 -0
  54. data/lib/acfs/version.rb +4 -2
  55. data/lib/acfs/yard.rb +1 -0
  56. data/spec/acfs/adapter/typhoeus_spec.rb +30 -3
  57. data/spec/acfs/collection_spec.rb +7 -5
  58. data/spec/acfs/configuration_spec.rb +2 -0
  59. data/spec/acfs/global_spec.rb +6 -3
  60. data/spec/acfs/location_spec.rb +2 -0
  61. data/spec/acfs/middleware/json_spec.rb +17 -1
  62. data/spec/acfs/middleware/msgpack_spec.rb +2 -0
  63. data/spec/acfs/operation_spec.rb +2 -0
  64. data/spec/acfs/request/callbacks_spec.rb +2 -0
  65. data/spec/acfs/request_spec.rb +3 -1
  66. data/spec/acfs/resource/attributes/boolean_spec.rb +2 -0
  67. data/spec/acfs/resource/attributes/date_time_spec.rb +2 -0
  68. data/spec/acfs/resource/attributes/dict_spec.rb +4 -2
  69. data/spec/acfs/resource/attributes/float_spec.rb +3 -1
  70. data/spec/acfs/resource/attributes/integer_spec.rb +2 -0
  71. data/spec/acfs/resource/attributes/list_spec.rb +5 -3
  72. data/spec/acfs/resource/attributes/uuid_spec.rb +2 -0
  73. data/spec/acfs/resource/attributes_spec.rb +8 -8
  74. data/spec/acfs/resource/dirty_spec.rb +2 -0
  75. data/spec/acfs/resource/initialization_spec.rb +8 -2
  76. data/spec/acfs/resource/loadable_spec.rb +2 -0
  77. data/spec/acfs/resource/locatable_spec.rb +2 -0
  78. data/spec/acfs/resource/persistance_spec.rb +10 -4
  79. data/spec/acfs/resource/query_methods_spec.rb +24 -17
  80. data/spec/acfs/resource/validation_spec.rb +2 -0
  81. data/spec/acfs/response/formats_spec.rb +3 -1
  82. data/spec/acfs/response/status_spec.rb +2 -0
  83. data/spec/acfs/runner_spec.rb +6 -8
  84. data/spec/acfs/service/middleware_spec.rb +2 -0
  85. data/spec/acfs/service_spec.rb +3 -1
  86. data/spec/acfs/singleton_resource_spec.rb +2 -0
  87. data/spec/acfs/stub_spec.rb +2 -0
  88. data/spec/acfs_spec.rb +2 -0
  89. data/spec/spec_helper.rb +3 -1
  90. data/spec/support/hash.rb +2 -0
  91. data/spec/support/response.rb +2 -0
  92. data/spec/support/service.rb +1 -0
  93. data/spec/support/shared/find_callbacks.rb +2 -0
  94. metadata +26 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9e970f81dff63a351279207100701f7a9be822272a77e5dfc3bd39d9e418a0db
4
- data.tar.gz: 81b752674659595a097b951334bb41fa36f9a96de2f3b7ff0a1a82d3e03f0009
3
+ metadata.gz: 55e1388e9df4207138b2a54f1e9d56c349ac407e52364b849887e9682abfee7e
4
+ data.tar.gz: ccf1b3550de8f5222988333d14e480ec07742fb0398d3adfb9504be4ca4168b4
5
5
  SHA512:
6
- metadata.gz: 4d8363f66d917672285318eaf1f68f03c3ef28c560373b4e74054f5d5d4da7dd0a443f6b54c9835fafbd290921e2d8316195a3c015970e539baa37fb8bead339
7
- data.tar.gz: 73d009dc5601ba4e4cc06efb41a0990a58779726b86ebf4905c2967dba55de406085b83e9a7c3de71b860e748bae1ff39b2a59de91a2699c488ced2d689d9234
6
+ metadata.gz: d34c6fd3d4e83e22757633efc72c8d399778b86665f4b5bb6fb46c8d4f93782f996fe307904ac83f9b16701157ecb8418977466cad9d9c5a78c6ea1074e9ddd7
7
+ data.tar.gz: 3460436cd3a9d61241155658e4c46ef556b69d00fd389aca73c78ca6484b29bac9b3c45a0fd310b41259aba68f8aad55c7ca95a259e18075c2d88b2515bacd52
@@ -14,6 +14,45 @@
14
14
  ### Breaks
15
15
 
16
16
 
17
+ ## 1.5.1 - (2020-12-30)
18
+ ---
19
+
20
+ ### Changes
21
+ * Revert back to using `::MultiJson`
22
+
23
+
24
+ ## 1.5.0 - (2020-06-19)
25
+ ---
26
+
27
+ ### New
28
+ * Error classes for more HTTP error responses: `400`, `401`, `403`, `500`, `502`, `503`, `504`.
29
+
30
+ ### Changes
31
+ * Replace deprecated MultiJson with core JSON module
32
+
33
+
34
+ ## 1.4.0 - (2020-06-12)
35
+ ---
36
+
37
+ ### New
38
+ * Use strict TCP keepalive probing by default (5s/5s)
39
+ * Adapter accepts curl request opts
40
+
41
+
42
+ ## 1.3.4 - (2020-03-22)
43
+ ---
44
+
45
+ ### Fixes
46
+ * Empty package build for Gem release 1.3.3
47
+
48
+
49
+ ## 1.3.3 - (2020-03-22)
50
+ ---
51
+
52
+ ### Changes
53
+ * Improved handling of low-level connection errors and timeouts
54
+
55
+
17
56
  ## 1.3.2 - (2019-09-24)
18
57
 
19
58
 
data/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # Acfs - *API client for services*
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/acfs.svg)](http://badge.fury.io/rb/acfs)
4
- [![Build Status](http://img.shields.io/travis/jgraichen/acfs/master.svg)](https://travis-ci.org/jgraichen/acfs)
3
+ [![Gem Version](https://img.shields.io/gem/v/acfs?logo=ruby)](https://rubygems.org/gems/acfs)
4
+ [![Build Status](https://img.shields.io/travis/jgraichen/acfs/master?logo=travis)](https://travis-ci.org/jgraichen/acfs)
5
+ [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/jgraichen/acfs/Test/master?logo=github)](https://github.com/jgraichen/acfs/actions?query=branch%3Amaster)
5
6
  [![Coverage Status](http://img.shields.io/coveralls/jgraichen/acfs/master.svg)](https://coveralls.io/r/jgraichen/acfs)
6
7
  [![RubyDoc Documentation](http://img.shields.io/badge/rubydoc-here-blue.svg)](http://rubydoc.info/github/jgraichen/acfs/master/frames)
7
8
 
@@ -9,6 +10,7 @@ Acfs is a library to develop API client libraries for single services within a l
9
10
 
10
11
  Acfs covers model and service abstraction, convenient query and filter methods, full middleware stack for pre-processing requests and responses on a per service level and automatic request queuing and parallel processing. See Usage for more.
11
12
 
13
+
12
14
  ## Installation
13
15
 
14
16
  Add this line to your application's Gemfile:
@@ -23,6 +25,7 @@ Or install it yourself as:
23
25
 
24
26
  > gem install acfs
25
27
 
28
+
26
29
  ## Usage
27
30
 
28
31
  First you need to define your service(s):
@@ -144,6 +147,7 @@ Acfs has basic update support using `PUT` requests:
144
147
  @user.persisted? # => true
145
148
  ```
146
149
 
150
+
147
151
  ## Singleton resources
148
152
 
149
153
  Singletons can be used in Acfs by creating a new resource which inherits from `SingletonResource`:
@@ -182,6 +186,7 @@ my_single = Single.find name: 'Max'
182
186
  Acfs.run # sends GET request with param to /single?name=Max
183
187
  ```
184
188
 
189
+
185
190
  ## Resource Inheritance
186
191
 
187
192
  Acfs provides a resource inheritance similar to ActiveRecord Single Table Inheritance. If a
@@ -218,6 +223,7 @@ Acfs.run
218
223
  @computer[2].class # => Pc
219
224
  ```
220
225
 
226
+
221
227
  ## Stubbing
222
228
 
223
229
  You can stub resources in applications using an Acfs service client:
@@ -278,6 +284,7 @@ it 'should find user number one' do
278
284
  end
279
285
  ```
280
286
 
287
+
281
288
  ## Instrumentation
282
289
 
283
290
  Acfs supports [instrumentation via active support][1].
@@ -295,21 +302,6 @@ Read [official guide][2] to see to to subscribe.
295
302
  [1]: http://guides.rubyonrails.org/active_support_instrumentation.html
296
303
  [2]: http://guides.rubyonrails.org/active_support_instrumentation.html#subscribing-to-an-event
297
304
 
298
- ## Roadmap
299
-
300
- * Update
301
- * Better new? detection eg. storing ETag from request resources.
302
- * Use PATCH for with only changed attributes and `If-Unmodifed-Since`
303
- and `If-Match` header fields if resource was surly loaded from service
304
- and not created with an id (e.g `User.new id: 5, name: "john"`).
305
- * Conflict detection (ETag / If-Unmodified-Since)
306
- * High level features
307
- * Support for custom mime types on client and server side. (`application/vnd.myservice.user.v2+msgpack`)
308
- * Server side components
309
- * Reusing model definitions for generating responses?
310
- * Rails responders providing REST operations with integrated ETag,
311
- Modified Headers, conflict detection, ...
312
- * Documentation
313
305
 
314
306
  ## Contributing
315
307
 
@@ -321,14 +313,9 @@ Read [official guide][2] to see to to subscribe.
321
313
  7. Push to the branch (`git push origin my-new-feature`)
322
314
  8. Create new Pull Request
323
315
 
324
- ## Contributors
325
-
326
- * [Nicolas Fricke](https://github.com/nicolas-fricke)
327
- * [Tino Junge](https://github.com/tino-junge)
328
- * [Malte Swart](https://github.com/mswart)
329
316
 
330
317
  ## License
331
318
 
332
319
  MIT License
333
320
 
334
- Copyright (c) 2013 Jan Graichen. MIT license, see LICENSE for more details.
321
+ Copyright (c) 2013-2020 Jan Graichen. MIT license, see LICENSE for more details.
@@ -1,5 +1,6 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'acfs/version'
5
6
 
@@ -7,31 +8,29 @@ Gem::Specification.new do |spec|
7
8
  spec.name = 'acfs'
8
9
  spec.version = Acfs::VERSION
9
10
  spec.authors = ['Jan Graichen']
10
- spec.email = %w(jg@altimos.de)
11
- spec.description = 'API Client For Services'
12
- spec.summary = 'An abstract API base client for service oriented application.'
11
+ spec.email = %w[jgraichen@altimos.de]
13
12
  spec.homepage = 'https://github.com/jgraichen/acfs'
14
13
  spec.license = 'MIT'
14
+ spec.description = 'API Client For Services'
15
+ spec.summary = <<~SUMMARY.strip
16
+ An abstract API base client for service oriented application.
17
+ SUMMARY
18
+
19
+ spec.files = Dir['**/*'].grep(%r{
20
+ ^((bin|lib|test|spec|features)/|
21
+ .*\.gemspec|.*LICENSE.*|.*README.*|.*CHANGELOG.*)
22
+ }xi)
15
23
 
16
- spec.files = Dir['**/*'].grep(%r{^((bin|lib|test|spec|features)/|.*\.gemspec|.*LICENSE.*|.*README.*|.*CHANGELOG.*)})
17
24
  spec.executables = spec.files.grep(%r{^bin/}) {|f| File.basename(f) }
18
25
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = %w(lib)
20
-
21
- spec.add_runtime_dependency 'activesupport', '>= 4.2'
22
- spec.add_runtime_dependency 'activemodel', '>= 4.2'
23
- spec.add_runtime_dependency 'actionpack', '>= 4.2'
24
- spec.add_runtime_dependency 'multi_json'
25
-
26
- # Bundle update w/o version resolves to 0.3.3 ...
27
- spec.add_runtime_dependency 'typhoeus', '~> 1.0'
26
+ spec.require_paths = %w[lib]
28
27
 
28
+ spec.add_runtime_dependency 'actionpack', '>= 5.2'
29
+ spec.add_runtime_dependency 'activemodel', '>= 5.2'
30
+ spec.add_runtime_dependency 'activesupport', '>= 5.2'
31
+ spec.add_runtime_dependency 'multi_json', '~> 1.0'
29
32
  spec.add_runtime_dependency 'rack'
33
+ spec.add_runtime_dependency 'typhoeus', '~> 1.0'
30
34
 
31
35
  spec.add_development_dependency 'bundler'
32
-
33
- if ENV['TRAVIS_BUILD_NUMBER'] && !ENV['TRAVIS_TAG']
34
- # Append travis build number for auto-releases
35
- spec.version = "#{spec.version}.1.b#{ENV['TRAVIS_BUILD_NUMBER']}"
36
- end
37
36
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support'
2
4
  require 'active_support/core_ext/hash'
3
5
  require 'active_support/core_ext/class'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs::Adapter
2
4
  # Base adapter handling operation queuing
3
5
  # and processing.
@@ -5,22 +7,18 @@ module Acfs::Adapter
5
7
  class Base
6
8
  # Start processing queued requests.
7
9
  #
8
- def start
9
- end
10
+ def start; end
10
11
 
11
12
  # Abort running and queued requests.
12
13
  #
13
- def abort
14
- end
14
+ def abort; end
15
15
 
16
16
  # Run request right now skipping queue.
17
17
  #
18
- def run(_)
19
- end
18
+ def run(_); end
20
19
 
21
20
  # Enqueue request to be run later.
22
21
  #
23
- def queue(_)
24
- end
22
+ def queue(_); end
25
23
  end
26
24
  end
@@ -1,17 +1,26 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'typhoeus'
2
4
 
3
5
  module Acfs
4
6
  module Adapter
7
+ DEFAULT_OPTIONS = {
8
+ tcp_keepalive: true,
9
+ tcp_keepidle: 5,
10
+ tcp_keepintvl: 5
11
+ }.freeze
12
+
5
13
  # Adapter for Typhoeus.
6
14
  #
7
15
  class Typhoeus < Base
8
- def initialize(**kwargs)
9
- @options = kwargs
16
+ def initialize(opts: {}, **kwargs)
17
+ @opts = DEFAULT_OPTIONS.merge(opts)
18
+ @kwargs = kwargs
10
19
  end
11
20
 
12
21
  def start
13
22
  hydra.run
14
- rescue
23
+ rescue StandardError
15
24
  @hydra = nil
16
25
  raise
17
26
  end
@@ -29,20 +38,30 @@ module Acfs
29
38
  protected
30
39
 
31
40
  def hydra
32
- @hydra ||= ::Typhoeus::Hydra.new(**@options)
41
+ @hydra ||= ::Typhoeus::Hydra.new(**@kwargs)
33
42
  end
34
43
 
35
44
  def convert_request(req)
36
- request = ::Typhoeus::Request.new req.url,
45
+ opts = {
37
46
  method: req.method,
38
47
  params: req.params,
39
48
  headers: req.headers.merge(
40
- 'Expect' => '',
49
+ 'Expect' => '',
41
50
  'Transfer-Encoding' => ''
42
51
  ),
43
52
  body: req.body
53
+ }
54
+
55
+ request = ::Typhoeus::Request.new(req.url, **@opts.merge(opts))
44
56
 
45
57
  request.on_complete do |response|
58
+ raise ::Acfs::TimeoutError.new(req) if response.timed_out?
59
+
60
+ if response.code.zero?
61
+ # Failed to get HTTP response
62
+ raise ::Acfs::RequestError.new(req, response.return_message)
63
+ end
64
+
46
65
  req.complete! convert_response(req, response)
47
66
  end
48
67
 
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'delegate'
2
4
 
3
5
  require 'acfs/resource/loadable'
4
6
  require 'acfs/collections/paginatable'
5
7
 
6
8
  module Acfs
7
- #
8
9
  class Collection < ::Delegator
9
10
  include Resource::Loadable
10
11
  include Acfs::Util::Callbacks
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs::Collections
2
- #
3
4
  module Paginatable
4
5
  extend ActiveSupport::Concern
5
6
 
@@ -67,8 +68,8 @@ module Acfs::Collections
67
68
  def setup_params(params)
68
69
  @current_page = begin
69
70
  Integer params.fetch(:page, 1)
70
- rescue ArgumentError
71
- params[:page]
71
+ rescue ArgumentError
72
+ params[:page]
72
73
  end
73
74
  end
74
75
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
  require 'yaml'
3
5
 
@@ -25,7 +27,7 @@ module Acfs
25
27
  # @return [undefined]
26
28
  #
27
29
  def configure(&block)
28
- if block.arity > 0
30
+ if block.arity.positive?
29
31
  block.call self
30
32
  else
31
33
  instance_eval(&block)
@@ -37,8 +39,12 @@ module Acfs
37
39
  # @overload locate(service, uri)
38
40
  # Configures URL where a service can be reached.
39
41
  #
40
- # @param [Symbol] service Service identity key for service that is reachable under given URL.
41
- # @param [String] uri URL where service is reachable. Will be passed to {URI.parse}.
42
+ # @param [Symbol] service
43
+ # Service identity key for service that is reachable under given URL.
44
+ #
45
+ # @param [String] uri
46
+ # URL where service is reachable. Will be passed to {URI.parse}.
47
+ #
42
48
  # @return [undefined]
43
49
  #
44
50
  # @overload locate(service)
@@ -64,7 +70,7 @@ module Acfs
64
70
  # @return [undefined]
65
71
  #
66
72
  def load(filename)
67
- config = YAML.load File.read filename
73
+ config = YAML.safe_load(File.read(filename), [], [], true)
68
74
  env = ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development'
69
75
 
70
76
  config = config[env] if config.key? env
@@ -95,18 +101,19 @@ module Acfs
95
101
  # @return [Configuration]
96
102
  #
97
103
  def current
98
- @configuration ||= new
104
+ @current ||= new
99
105
  end
100
106
 
101
107
  # @api private
102
108
  #
103
- # Swap configuration object with given new one. Must be a {Configuration} object.
109
+ # Swap configuration object with given new one. Must be
110
+ # a {Configuration} object.
104
111
  #
105
112
  # @param [Configuration] configuration
106
113
  # @return [undefined]
107
114
  #
108
115
  def set(configuration)
109
- @configuration = configuration if configuration.is_a? Configuration
116
+ @current = configuration if configuration.is_a? Configuration
110
117
  end
111
118
  end
112
119
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs
2
4
  # Acfs base error.
3
5
  #
@@ -10,6 +12,24 @@ module Acfs
10
12
 
11
13
  class UnsupportedOperation < StandardError; end
12
14
 
15
+ class RequestError < Error
16
+ attr_reader :request
17
+
18
+ def initialize(request, message)
19
+ @request = request
20
+
21
+ message = "#{message}: #{request.method.upcase} #{request.url}"
22
+
23
+ super message: message
24
+ end
25
+ end
26
+
27
+ class TimeoutError < RequestError
28
+ def initialize(request)
29
+ super(request, 'Timeout reached')
30
+ end
31
+ end
32
+
13
33
  # Response error containing the responsible response object.
14
34
  #
15
35
  class ErroneousResponse < Error
@@ -17,17 +37,15 @@ module Acfs
17
37
 
18
38
  def initialize(opts = {})
19
39
  @response = opts[:response]
20
- message = opts[:message]
21
- if response
22
- if message
23
- message << ':'
24
- else
25
- message = 'Received'
26
- end
27
- message << " #{response.code} for #{response.request.method.upcase} #{response.request.url} #{response.request.format}"
28
- else
29
- message ||= 'Received erroneous response'
30
- end
40
+
41
+ message = if response
42
+ (opts[:message] ? opts[:message] + ':' : 'Received') +
43
+ " #{response.code} for #{response.request.method.upcase}" \
44
+ " #{response.request.url} #{response.request.format}"
45
+ else
46
+ opts[:message] || 'Received erroneous response'
47
+ end
48
+
31
49
  super opts, message
32
50
  end
33
51
  end
@@ -41,17 +59,27 @@ module Acfs
41
59
  @stubs = opts.delete :stubs
42
60
  @operation = opts.delete :operation
43
61
 
44
- super opts, "Ambiguous stubs for #{operation.action} on #{operation.resource}.\n" +
45
- stubs.map {|s| " #{s.opts.pretty_inspect}" }.join
62
+ message = "Ambiguous stubs for #{operation.action} " \
63
+ "on #{operation.resource}.\n" +
64
+ stubs.map {|s| " #{s.opts.pretty_inspect}" }.join
65
+
66
+ super opts, message
46
67
  end
47
68
  end
48
69
 
49
- # Resource not found error raised on a 404 response
50
- #
51
- class ResourceNotFound < ErroneousResponse
52
- end
70
+ # 400
71
+ class BadRequest < ErroneousResponse; end
53
72
 
54
- #
73
+ # 401
74
+ class Unauthorized < ErroneousResponse; end
75
+
76
+ # 403
77
+ class Forbidden < ErroneousResponse; end
78
+
79
+ # 404
80
+ class ResourceNotFound < ErroneousResponse; end
81
+
82
+ # 422
55
83
  class InvalidResource < ErroneousResponse
56
84
  attr_reader :errors, :resource
57
85
 
@@ -71,6 +99,18 @@ module Acfs
71
99
  end
72
100
  end
73
101
 
102
+ # 500
103
+ class ServerError < ErroneousResponse; end
104
+
105
+ # 502
106
+ class BadGateway < ErroneousResponse; end
107
+
108
+ # 503
109
+ class ServiceUnavailable < ErroneousResponse; end
110
+
111
+ # 504
112
+ class GatewayTimeout < ErroneousResponse; end
113
+
74
114
  # A ResourceNotLoaded error will be thrown when calling some
75
115
  # modifing methods on not loaded resources as it is usally
76
116
  # unwanted to call e.g. `update_attributes` on a not loaded
@@ -97,7 +137,8 @@ module Acfs
97
137
  def initialize(opts = {})
98
138
  @base_class = opts.delete :base_class
99
139
  @type_name = opts.delete :type_name
100
- opts[:message] = "Received resource type `#{type_name}` is no subclass of #{base_class}"
140
+ opts[:message] = "Received resource type `#{type_name}` " \
141
+ "is no subclass of #{base_class}"
101
142
  super
102
143
  end
103
144
  end