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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs
2
4
  #
3
5
  # Global Acfs module methods.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs
2
4
  # @api private
3
5
  #
@@ -6,7 +8,7 @@ module Acfs
6
8
  class Location
7
9
  attr_reader :arguments, :raw, :struct, :args
8
10
 
9
- REGEXP = /^:([A-z][A-z0-9_]*)$/
11
+ REGEXP = /^:([A-z][A-z0-9_]*)$/.freeze
10
12
 
11
13
  def initialize(uri, args = {})
12
14
  @raw = URI.parse uri
@@ -40,13 +42,15 @@ module Acfs
40
42
  def raw_uri
41
43
  raw.to_s
42
44
  end
43
- alias_method :to_s, :raw_uri
45
+ alias to_s raw_uri
44
46
 
45
47
  private
46
48
 
47
49
  def extract_arg(key, hashes)
48
50
  hashes.each_with_index do |hash, index|
49
- return (index == 0 ? hash.delete(key) : hash.fetch(key)) if hash.key?(key)
51
+ if hash.key?(key)
52
+ return (index.zero? ? hash.delete(key) : hash.fetch(key))
53
+ end
50
54
  end
51
55
 
52
56
  nil
@@ -68,9 +72,9 @@ module Acfs
68
72
  args.fetch(sym) do
69
73
  if args[:raise].nil? || args[:raise]
70
74
  raise ArgumentError.new "URI path argument `#{sym}' missing on `#{self}'. Given: `#{args}.inspect'"
71
- else
72
- ":#{sym}"
73
75
  end
76
+
77
+ ":#{sym}"
74
78
  end
75
79
  end
76
80
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs
2
4
  module Middleware
3
5
  # A base middleware that does not modify request or response.
@@ -12,7 +14,9 @@ module Acfs
12
14
  end
13
15
 
14
16
  def call(request)
15
- request.on_complete {|res, nxt| response(res, nxt) } if respond_to? :response
17
+ if respond_to? :response
18
+ request.on_complete {|res, nxt| response(res, nxt) }
19
+ end
16
20
  app.call(request)
17
21
  end
18
22
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'multi_json'
2
4
 
3
5
  module Acfs
@@ -10,11 +12,13 @@ module Acfs
10
12
  end
11
13
 
12
14
  def encode(data)
13
- ::MultiJson.dump data
15
+ ::MultiJson.dump(data)
14
16
  end
15
17
 
16
18
  def decode(body)
17
- ::MultiJson.load body
19
+ ::MultiJson.load(body)
20
+ rescue ::MultiJson::ParseError => e
21
+ raise ::JSON::ParserError.new(e)
18
22
  end
19
23
  end
20
24
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'logger'
2
4
 
3
5
  module Acfs
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'msgpack'
2
4
  require 'action_dispatch'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs
2
4
  module Middleware
3
5
  # Print resquests and response on terminal
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs
2
4
  module Middleware
3
5
  # A base middleware that does not modify request or response.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs
2
4
  # @api private
3
5
  #
@@ -6,6 +8,7 @@ module Acfs
6
8
  #
7
9
  class Operation
8
10
  attr_reader :action, :params, :resource, :data, :callback, :location, :url
11
+
9
12
  delegate :service, to: :resource
10
13
  delegate :call, to: :callback
11
14
 
@@ -19,7 +22,7 @@ module Acfs
19
22
  @data = (opts[:data] || {}).dup
20
23
 
21
24
  if opts[:url]
22
- @url = opts[:url]
25
+ @url = opts[:url]
23
26
  else
24
27
  @location = resource.location(action: @action).extract_from(@params, @data)
25
28
  @url = location.str
@@ -29,11 +32,11 @@ module Acfs
29
32
  end
30
33
 
31
34
  def single?
32
- [:read, :update, :delete].include? action
35
+ %i[read update delete].include? action
33
36
  end
34
37
 
35
38
  def synchronous?
36
- [:update, :delete, :create].include? action
39
+ %i[update delete create].include? action
37
40
  end
38
41
 
39
42
  def id
@@ -69,10 +72,24 @@ module Acfs
69
72
 
70
73
  def handle_failure(response)
71
74
  case response.code
75
+ when 400
76
+ raise ::Acfs::BadRequest.new response: response
77
+ when 401
78
+ raise ::Acfs::Unauthorized.new response: response
79
+ when 403
80
+ raise ::Acfs::Forbidden.new response: response
72
81
  when 404
73
82
  raise ::Acfs::ResourceNotFound.new response: response
74
83
  when 422
75
84
  raise ::Acfs::InvalidResource.new response: response, errors: response.data.try(:[], 'errors')
85
+ when 500
86
+ raise ::Acfs::ServerError.new response: response
87
+ when 502
88
+ raise ::Acfs::BadGateway.new response: response
89
+ when 503
90
+ raise ::Acfs::ServiceUnavailable.new response: response
91
+ when 504
92
+ raise ::Acfs::GatewayTimeout.new response: response
76
93
  else
77
94
  raise ::Acfs::ErroneousResponse.new response: response
78
95
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'acfs/request/callbacks'
2
4
 
3
5
  module Acfs
@@ -9,7 +11,6 @@ module Acfs
9
11
  attr_reader :url, :headers, :params, :data, :method, :operation
10
12
 
11
13
  include Request::Callbacks
12
-
13
14
  def initialize(url, options = {}, &block)
14
15
  @url = URI.parse(url.to_s).tap do |_url|
15
16
  @data = options.delete(:data) || nil
@@ -18,7 +19,9 @@ module Acfs
18
19
  @params = options.delete(:params) || {}
19
20
  @method = options.delete(:method) || :get
20
21
  end.to_s
22
+
21
23
  @operation = options.delete(:operation) || nil
24
+
22
25
  on_complete(&block) if block_given?
23
26
  end
24
27
 
@@ -29,6 +32,7 @@ module Acfs
29
32
  class << self
30
33
  def new(*attrs)
31
34
  return attrs[0] if attrs[0].is_a? self
35
+
32
36
  super
33
37
  end
34
38
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs
2
4
  class Request
3
5
  # Module containing callback handling for Requests.
@@ -43,7 +45,9 @@ module Acfs
43
45
  private
44
46
 
45
47
  def call_callback(res, index)
46
- callbacks[index].call res, proc {|bres| call_callback bres, index + 1 } if index < callbacks.size
48
+ return if index >= callbacks.size
49
+
50
+ callbacks[index].call(res, proc {|bres| call_callback bres, index + 1 })
47
51
  end
48
52
  end
49
53
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_model'
2
4
 
3
5
  # @api public
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Acfs::Resource
2
4
  #
3
5
  # = Acfs Attributes
@@ -46,9 +48,11 @@ class Acfs::Resource
46
48
  # @return [HashWithIndifferentAccess{Symbol => Object}]
47
49
  # Attributes and their values.
48
50
  #
51
+ # rubocop:disable Naming/MemoizedInstanceVariableName
49
52
  def attributes
50
53
  @_attrs ||= HashWithIndifferentAccess.new
51
54
  end
55
+ # rubocop:enable Naming/MemoizedInstanceVariableName
52
56
 
53
57
  # @api public
54
58
  #
@@ -176,9 +180,8 @@ class Acfs::Resource
176
180
  attributes[name.to_s] = value
177
181
  end
178
182
 
179
- #
180
183
  module ClassMethods
181
- ATTR_CLASS_BASE = '::Acfs::Resource::Attributes'.freeze
184
+ ATTR_CLASS_BASE = '::Acfs::Resource::Attributes'
182
185
 
183
186
  #
184
187
  # @api public
@@ -241,9 +244,9 @@ class Acfs::Resource
241
244
  @local_attributes ||= {}
242
245
  end
243
246
 
244
- def define_attribute(name, type, opts = {})
247
+ def define_attribute(name, type, **opts)
245
248
  name = name.to_s
246
- attribute = type.new opts
249
+ attribute = type.new(**opts)
247
250
 
248
251
  local_attributes[name] = attribute
249
252
  define_attribute_method name
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs::Resource::Attributes
2
- #
3
4
  class Base
4
5
  attr_reader :default
5
6
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs::Resource::Attributes
2
4
  # @api public
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs::Resource::Attributes
2
4
  # @api public
3
5
  #
@@ -10,7 +12,6 @@ module Acfs::Resource::Attributes
10
12
  # end
11
13
  #
12
14
  class DateTime < Base
13
-
14
15
  # @api public
15
16
  #
16
17
  # Cast given object to DateTime.
@@ -21,7 +22,7 @@ module Acfs::Resource::Attributes
21
22
  def cast_value(value)
22
23
  if value.blank?
23
24
  nil
24
- elsif value.acts_like?(:time) || value.acts_like?(:date)
25
+ elsif !value.is_a?(::String) && value.respond_to?(:to_datetime)
25
26
  value.to_datetime
26
27
  else
27
28
  ::DateTime.iso8601 value
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs::Resource::Attributes
2
4
  # @api public
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs::Resource::Attributes
2
4
  # @api public
3
5
  #
@@ -21,9 +23,9 @@ module Acfs::Resource::Attributes
21
23
 
22
24
  case value
23
25
  when ::Float then value
24
- when "Infinity" then ::Float::INFINITY
25
- when "-Infinity" then -::Float::INFINITY
26
- when "NaN" then ::Float::NAN
26
+ when 'Infinity' then ::Float::INFINITY
27
+ when '-Infinity' then -::Float::INFINITY
28
+ when 'NaN' then ::Float::NAN
27
29
  else Float(value)
28
30
  end
29
31
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs::Resource::Attributes
2
4
  # @api public
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs::Resource::Attributes
2
4
  # @api public
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs::Resource::Attributes
2
4
  # @api public
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs::Resource::Attributes
2
4
  # @api public
3
5
  #
@@ -9,8 +11,7 @@ module Acfs::Resource::Attributes
9
11
  # end
10
12
  #
11
13
  class UUID < Base
12
- #
13
- UUID_REGEXP = /[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}/i
14
+ UUID_REGEXP = /[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}/i.freeze
14
15
 
15
16
  # @api public
16
17
  #
@@ -37,7 +38,7 @@ module Acfs::Resource::Attributes
37
38
  elsif value.to_s =~ UUID_REGEXP
38
39
  value
39
40
  else
40
- raise TypeError.new "Invalid UUID: `#{value.to_s}'"
41
+ raise TypeError.new "Invalid UUID: `#{value}'"
41
42
  end
42
43
  end
43
44
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Acfs::Resource
2
4
  #
3
5
  # Thin wrapper around ActiveModel::Dirty
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Acfs::Resource
2
4
  #
3
5
  # Initialization drop-in for pre-4.0 ActiveModel.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Acfs::Resource
2
4
  # Provides method to check for loading state of resources.
3
5
  # A resource that is created but not yet fetched will be loaded
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Acfs::Resource
2
4
  # Provide methods for generation URLs for resources.
3
5
  #
@@ -11,7 +13,6 @@ class Acfs::Resource
11
13
  module Locatable
12
14
  extend ActiveSupport::Concern
13
15
 
14
- #
15
16
  module ClassMethods
16
17
  # @overload url(suffix)
17
18
  # @deprecated
@@ -40,7 +41,10 @@ class Acfs::Resource
40
41
  # @return [String] Generated URL.
41
42
  #
42
43
  def url(suffix = nil, opts = {})
43
- opts, suffix = suffix, nil if suffix.is_a? Hash
44
+ if suffix.is_a? Hash
45
+ opts = suffix
46
+ suffix = nil
47
+ end
44
48
 
45
49
  opts[:action] = :list if suffix
46
50
 
@@ -85,9 +89,9 @@ class Acfs::Resource
85
89
  def location_default_path(action, path)
86
90
  case action
87
91
  when :list, :create
88
- return path
92
+ path
89
93
  when :read, :update, :delete
90
- return "#{path}/:id"
94
+ "#{path}/:id"
91
95
  end
92
96
  end
93
97
  end
@@ -109,8 +113,8 @@ class Acfs::Resource
109
113
  return nil if need_primary_key? && !primary_key?
110
114
 
111
115
  self.class.service
112
- .location(self.class, opts.reverse_merge(action: :read))
113
- .build(attributes).str
116
+ .location(self.class, opts.reverse_merge(action: :read))
117
+ .build(attributes).str
114
118
  end
115
119
 
116
120
  # @api private