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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +39 -0
- data/README.md +10 -23
- data/acfs.gemspec +19 -20
- data/lib/acfs.rb +2 -0
- data/lib/acfs/adapter/base.rb +6 -8
- data/lib/acfs/adapter/typhoeus.rb +25 -6
- data/lib/acfs/collection.rb +2 -1
- data/lib/acfs/collections/paginatable.rb +4 -3
- data/lib/acfs/configuration.rb +14 -7
- data/lib/acfs/errors.rb +60 -19
- data/lib/acfs/global.rb +2 -0
- data/lib/acfs/location.rb +9 -5
- data/lib/acfs/middleware/base.rb +5 -1
- data/lib/acfs/middleware/json.rb +6 -2
- data/lib/acfs/middleware/logger.rb +2 -0
- data/lib/acfs/middleware/msgpack.rb +2 -0
- data/lib/acfs/middleware/print.rb +2 -0
- data/lib/acfs/middleware/serializer.rb +2 -0
- data/lib/acfs/operation.rb +20 -3
- data/lib/acfs/request.rb +5 -1
- data/lib/acfs/request/callbacks.rb +5 -1
- data/lib/acfs/resource.rb +2 -0
- data/lib/acfs/resource/attributes.rb +7 -4
- data/lib/acfs/resource/attributes/base.rb +2 -1
- data/lib/acfs/resource/attributes/boolean.rb +2 -0
- data/lib/acfs/resource/attributes/date_time.rb +3 -2
- data/lib/acfs/resource/attributes/dict.rb +2 -0
- data/lib/acfs/resource/attributes/float.rb +5 -3
- data/lib/acfs/resource/attributes/integer.rb +2 -0
- data/lib/acfs/resource/attributes/list.rb +2 -0
- data/lib/acfs/resource/attributes/string.rb +2 -0
- data/lib/acfs/resource/attributes/uuid.rb +4 -3
- data/lib/acfs/resource/dirty.rb +2 -0
- data/lib/acfs/resource/initialization.rb +2 -0
- data/lib/acfs/resource/loadable.rb +2 -0
- data/lib/acfs/resource/locatable.rb +10 -6
- data/lib/acfs/resource/operational.rb +2 -1
- data/lib/acfs/resource/persistence.rb +7 -6
- data/lib/acfs/resource/query_methods.rb +6 -4
- data/lib/acfs/resource/service.rb +3 -1
- data/lib/acfs/resource/validation.rb +19 -7
- data/lib/acfs/response.rb +2 -0
- data/lib/acfs/response/formats.rb +2 -0
- data/lib/acfs/response/status.rb +3 -1
- data/lib/acfs/rspec.rb +2 -0
- data/lib/acfs/runner.rb +6 -1
- data/lib/acfs/service.rb +24 -13
- data/lib/acfs/service/middleware.rb +2 -0
- data/lib/acfs/service/middleware/stack.rb +5 -3
- data/lib/acfs/singleton_resource.rb +4 -2
- data/lib/acfs/stub.rb +32 -11
- data/lib/acfs/util.rb +2 -0
- data/lib/acfs/version.rb +4 -2
- data/lib/acfs/yard.rb +1 -0
- data/spec/acfs/adapter/typhoeus_spec.rb +30 -3
- data/spec/acfs/collection_spec.rb +7 -5
- data/spec/acfs/configuration_spec.rb +2 -0
- data/spec/acfs/global_spec.rb +6 -3
- data/spec/acfs/location_spec.rb +2 -0
- data/spec/acfs/middleware/json_spec.rb +17 -1
- data/spec/acfs/middleware/msgpack_spec.rb +2 -0
- data/spec/acfs/operation_spec.rb +2 -0
- data/spec/acfs/request/callbacks_spec.rb +2 -0
- data/spec/acfs/request_spec.rb +3 -1
- data/spec/acfs/resource/attributes/boolean_spec.rb +2 -0
- data/spec/acfs/resource/attributes/date_time_spec.rb +2 -0
- data/spec/acfs/resource/attributes/dict_spec.rb +4 -2
- data/spec/acfs/resource/attributes/float_spec.rb +3 -1
- data/spec/acfs/resource/attributes/integer_spec.rb +2 -0
- data/spec/acfs/resource/attributes/list_spec.rb +5 -3
- data/spec/acfs/resource/attributes/uuid_spec.rb +2 -0
- data/spec/acfs/resource/attributes_spec.rb +8 -8
- data/spec/acfs/resource/dirty_spec.rb +2 -0
- data/spec/acfs/resource/initialization_spec.rb +8 -2
- data/spec/acfs/resource/loadable_spec.rb +2 -0
- data/spec/acfs/resource/locatable_spec.rb +2 -0
- data/spec/acfs/resource/persistance_spec.rb +10 -4
- data/spec/acfs/resource/query_methods_spec.rb +24 -17
- data/spec/acfs/resource/validation_spec.rb +2 -0
- data/spec/acfs/response/formats_spec.rb +3 -1
- data/spec/acfs/response/status_spec.rb +2 -0
- data/spec/acfs/runner_spec.rb +6 -8
- data/spec/acfs/service/middleware_spec.rb +2 -0
- data/spec/acfs/service_spec.rb +3 -1
- data/spec/acfs/singleton_resource_spec.rb +2 -0
- data/spec/acfs/stub_spec.rb +2 -0
- data/spec/acfs_spec.rb +2 -0
- data/spec/spec_helper.rb +3 -1
- data/spec/support/hash.rb +2 -0
- data/spec/support/response.rb +2 -0
- data/spec/support/service.rb +1 -0
- data/spec/support/shared/find_callbacks.rb +2 -0
- metadata +26 -26
data/lib/acfs/global.rb
CHANGED
data/lib/acfs/location.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
data/lib/acfs/middleware/base.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/acfs/middleware/json.rb
CHANGED
@@ -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
|
15
|
+
::MultiJson.dump(data)
|
14
16
|
end
|
15
17
|
|
16
18
|
def decode(body)
|
17
|
-
::MultiJson.load
|
19
|
+
::MultiJson.load(body)
|
20
|
+
rescue ::MultiJson::ParseError => e
|
21
|
+
raise ::JSON::ParserError.new(e)
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
data/lib/acfs/operation.rb
CHANGED
@@ -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
|
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
|
-
[
|
35
|
+
%i[read update delete].include? action
|
33
36
|
end
|
34
37
|
|
35
38
|
def synchronous?
|
36
|
-
[
|
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
|
data/lib/acfs/request.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/acfs/resource.rb
CHANGED
@@ -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'
|
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
|
249
|
+
attribute = type.new(**opts)
|
247
250
|
|
248
251
|
local_attributes[name] = attribute
|
249
252
|
define_attribute_method name
|
@@ -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.
|
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
|
#
|
@@ -21,9 +23,9 @@ module Acfs::Resource::Attributes
|
|
21
23
|
|
22
24
|
case value
|
23
25
|
when ::Float then value
|
24
|
-
when
|
25
|
-
when
|
26
|
-
when
|
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
|
#
|
@@ -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
|
41
|
+
raise TypeError.new "Invalid UUID: `#{value}'"
|
41
42
|
end
|
42
43
|
end
|
43
44
|
end
|
data/lib/acfs/resource/dirty.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
92
|
+
path
|
89
93
|
when :read, :update, :delete
|
90
|
-
|
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
|
-
|
113
|
-
|
116
|
+
.location(self.class, opts.reverse_merge(action: :read))
|
117
|
+
.build(attributes).str
|
114
118
|
end
|
115
119
|
|
116
120
|
# @api private
|