acfs 0.50.0 → 1.0.0.dev.1.b297
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/CHANGELOG.md +0 -80
- data/README.md +9 -8
- data/acfs.gemspec +7 -7
- data/lib/acfs.rb +5 -7
- data/lib/acfs/adapter/base.rb +2 -0
- data/lib/acfs/adapter/typhoeus.rb +13 -17
- data/lib/acfs/collections/paginatable.rb +10 -10
- data/lib/acfs/configuration.rb +5 -4
- data/lib/acfs/errors.rb +9 -10
- data/lib/acfs/global.rb +7 -16
- data/lib/acfs/location.rb +11 -11
- data/lib/acfs/middleware/base.rb +2 -1
- data/lib/acfs/middleware/json_decoder.rb +16 -0
- data/lib/acfs/middleware/json_encoder.rb +20 -0
- data/lib/acfs/middleware/logger.rb +2 -0
- data/lib/acfs/middleware/msgpack_decoder.rb +26 -0
- data/lib/acfs/middleware/msgpack_encoder.rb +19 -0
- data/lib/acfs/middleware/print.rb +2 -0
- data/lib/acfs/operation.rb +5 -5
- data/lib/acfs/request.rb +4 -4
- data/lib/acfs/request/callbacks.rb +3 -2
- data/lib/acfs/resource.rb +2 -2
- data/lib/acfs/resource/attributes.rb +38 -11
- data/lib/acfs/resource/attributes/base.rb +19 -10
- data/lib/acfs/resource/attributes/boolean.rb +8 -10
- data/lib/acfs/resource/attributes/date_time.rb +9 -6
- data/lib/acfs/resource/attributes/float.rb +5 -11
- data/lib/acfs/resource/attributes/integer.rb +5 -7
- data/lib/acfs/resource/attributes/list.rb +6 -13
- data/lib/acfs/resource/attributes/string.rb +5 -3
- data/lib/acfs/resource/attributes/uuid.rb +17 -8
- data/lib/acfs/resource/dirty.rb +15 -3
- data/lib/acfs/resource/loadable.rb +1 -0
- data/lib/acfs/resource/locatable.rb +4 -0
- data/lib/acfs/resource/operational.rb +2 -0
- data/lib/acfs/resource/persistence.rb +17 -17
- data/lib/acfs/resource/query_methods.rb +7 -8
- data/lib/acfs/resource/service.rb +2 -0
- data/lib/acfs/resource/validation.rb +4 -4
- data/lib/acfs/response.rb +2 -1
- data/lib/acfs/response/formats.rb +3 -2
- data/lib/acfs/response/status.rb +5 -3
- data/lib/acfs/runner.rb +11 -21
- data/lib/acfs/service.rb +6 -4
- data/lib/acfs/service/middleware.rb +30 -20
- data/lib/acfs/singleton_resource.rb +2 -0
- data/lib/acfs/stub.rb +21 -30
- data/lib/acfs/util.rb +1 -1
- data/lib/acfs/version.rb +4 -6
- data/spec/acfs/adapter/typhoeus_spec.rb +4 -12
- data/spec/acfs/collection_spec.rb +33 -45
- data/spec/acfs/configuration_spec.rb +1 -9
- data/spec/acfs/global_spec.rb +3 -21
- data/spec/acfs/middleware/json_decoder_spec.rb +45 -0
- data/spec/acfs/middleware/msgpack_decoder_spec.rb +36 -0
- data/spec/acfs/request/callbacks_spec.rb +8 -8
- data/spec/acfs/request_spec.rb +5 -5
- data/spec/acfs/resource/attributes/boolean_spec.rb +9 -40
- data/spec/acfs/resource/attributes/date_time_spec.rb +35 -29
- data/spec/acfs/resource/attributes/float_spec.rb +9 -48
- data/spec/acfs/resource/attributes/list_spec.rb +19 -43
- data/spec/acfs/resource/attributes/uuid_spec.rb +54 -31
- data/spec/acfs/resource/attributes_spec.rb +31 -17
- data/spec/acfs/resource/locatable_spec.rb +2 -2
- data/spec/acfs/resource/persistance_spec.rb +34 -65
- data/spec/acfs/resource/query_methods_spec.rb +90 -97
- data/spec/acfs/resource/validation_spec.rb +5 -4
- data/spec/acfs/response/formats_spec.rb +4 -4
- data/spec/acfs/response/status_spec.rb +1 -1
- data/spec/acfs/runner_spec.rb +3 -28
- data/spec/acfs/service/middleware_spec.rb +20 -4
- data/spec/acfs/service_spec.rb +5 -3
- data/spec/acfs/singleton_resource_spec.rb +2 -1
- data/spec/acfs/stub_spec.rb +22 -137
- data/spec/acfs_spec.rb +19 -22
- data/spec/spec_helper.rb +2 -3
- data/spec/support/service.rb +6 -10
- data/spec/support/shared/find_callbacks.rb +7 -7
- metadata +36 -43
- data/lib/acfs/middleware/json.rb +0 -27
- data/lib/acfs/middleware/msgpack.rb +0 -30
- data/lib/acfs/middleware/serializer.rb +0 -39
- data/lib/acfs/resource/attributes/dict.rb +0 -37
- data/lib/acfs/service/middleware/stack.rb +0 -63
- data/spec/acfs/middleware/json_spec.rb +0 -63
- data/spec/acfs/middleware/msgpack_spec.rb +0 -60
- data/spec/acfs/operation_spec.rb +0 -10
- data/spec/acfs/resource/attributes/dict_spec.rb +0 -75
- data/spec/acfs/resource/attributes/integer_spec.rb +0 -34
data/lib/acfs/response.rb
CHANGED
@@ -3,6 +3,7 @@ require 'acfs/response/status'
|
|
3
3
|
require 'active_support/core_ext/module/delegation'
|
4
4
|
|
5
5
|
module Acfs
|
6
|
+
|
6
7
|
# This represents a response. In addition to an standard HTTP
|
7
8
|
# it has a field `data` for storing the encoded body.
|
8
9
|
#
|
@@ -13,7 +14,7 @@ module Acfs
|
|
13
14
|
include Response::Formats
|
14
15
|
include Response::Status
|
15
16
|
|
16
|
-
#
|
17
|
+
#delegate :status, :status_message, :success?, :modified?, :timed_out?,
|
17
18
|
# :response_body, :response_headers, :response_code, :headers,
|
18
19
|
# to: :response
|
19
20
|
|
@@ -2,18 +2,19 @@ require 'action_dispatch'
|
|
2
2
|
|
3
3
|
module Acfs
|
4
4
|
class Response
|
5
|
+
|
5
6
|
# Quick accessors for format handling.
|
6
7
|
module Formats
|
8
|
+
|
7
9
|
def content_type
|
8
10
|
@content_type ||= read_content_type
|
9
11
|
end
|
10
12
|
|
11
13
|
def json?
|
12
|
-
content_type == Mime
|
14
|
+
content_type == Mime::JSON
|
13
15
|
end
|
14
16
|
|
15
17
|
private
|
16
|
-
|
17
18
|
def read_content_type
|
18
19
|
return 'text/plain' unless headers && headers['Content-Type']
|
19
20
|
|
data/lib/acfs/response/status.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
1
|
module Acfs
|
2
2
|
class Response
|
3
|
+
|
3
4
|
# Method to fetch information about response status.
|
4
5
|
#
|
5
6
|
module Status
|
7
|
+
|
6
8
|
# Return response status code. Will return zero if
|
7
9
|
# request was not executed or failed on client side.
|
8
10
|
#
|
9
11
|
def status_code
|
10
12
|
return @status.to_i if defined? :@status
|
11
|
-
#
|
12
|
-
#
|
13
|
+
#return response.response_code unless response.nil?
|
14
|
+
#0
|
13
15
|
end
|
14
|
-
|
16
|
+
alias :code :status_code
|
15
17
|
|
16
18
|
# Return true if response was successful indicated by
|
17
19
|
# response status code.
|
data/lib/acfs/runner.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'acfs/service/middleware'
|
2
2
|
|
3
3
|
module Acfs
|
4
|
+
|
4
5
|
# @api private
|
5
6
|
#
|
6
7
|
class Runner
|
@@ -16,7 +17,6 @@ module Acfs
|
|
16
17
|
# and parallel operations will be queued.
|
17
18
|
#
|
18
19
|
def process(op)
|
19
|
-
::ActiveSupport::Notifications.instrument 'acfs.operation.before_process', operation: op
|
20
20
|
op.synchronous? ? run(op) : enqueue(op)
|
21
21
|
end
|
22
22
|
|
@@ -24,7 +24,7 @@ module Acfs
|
|
24
24
|
#
|
25
25
|
def run(op)
|
26
26
|
::ActiveSupport::Notifications.instrument 'acfs.runner.sync_run', operation: op do
|
27
|
-
op_request(op) {|req| adapter.run req }
|
27
|
+
op_request(op) { |req| adapter.run req }
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -39,7 +39,7 @@ module Acfs
|
|
39
39
|
def enqueue(op)
|
40
40
|
::ActiveSupport::Notifications.instrument 'acfs.runner.enqueue', operation: op do
|
41
41
|
if running?
|
42
|
-
op_request(op) {|req| adapter.queue req }
|
42
|
+
op_request(op) { |req| adapter.queue req }
|
43
43
|
else
|
44
44
|
queue << op
|
45
45
|
end
|
@@ -55,13 +55,15 @@ module Acfs
|
|
55
55
|
# Start processing queued operations.
|
56
56
|
#
|
57
57
|
def start
|
58
|
-
return if running?
|
59
|
-
|
60
58
|
enqueue_operations
|
61
|
-
|
59
|
+
|
60
|
+
@running = true
|
61
|
+
adapter.start
|
62
62
|
rescue
|
63
63
|
queue.clear
|
64
64
|
raise
|
65
|
+
ensure
|
66
|
+
@running = false
|
65
67
|
end
|
66
68
|
|
67
69
|
def clear
|
@@ -71,27 +73,15 @@ module Acfs
|
|
71
73
|
end
|
72
74
|
|
73
75
|
private
|
74
|
-
|
75
|
-
def start_all
|
76
|
-
@running = true
|
77
|
-
adapter.start
|
78
|
-
ensure
|
79
|
-
@running = false
|
80
|
-
end
|
81
|
-
|
82
76
|
def enqueue_operations
|
83
77
|
while (op = queue.shift)
|
84
|
-
op_request(op) {|req| adapter.queue req }
|
78
|
+
op_request(op) { |req| adapter.queue req }
|
85
79
|
end
|
86
80
|
end
|
87
81
|
|
88
82
|
def op_request(op)
|
89
|
-
return if Acfs::Stub.enabled?
|
90
|
-
|
91
|
-
return unless req.is_a? Acfs::Request
|
92
|
-
req = prepare req
|
93
|
-
return unless req.is_a? Acfs::Request
|
94
|
-
yield req
|
83
|
+
return if Acfs::Stub.enabled? and Acfs::Stub.stubbed(op)
|
84
|
+
yield prepare op.service.prepare op.request
|
95
85
|
end
|
96
86
|
end
|
97
87
|
end
|
data/lib/acfs/service.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'acfs/service/middleware'
|
2
2
|
|
3
3
|
module Acfs
|
4
|
+
|
4
5
|
# User {Acfs::Service} to define your services. That includes
|
5
6
|
# an identity used to identify the service in configuration files
|
6
7
|
# and middlewares the service uses.
|
@@ -34,14 +35,14 @@ module Acfs
|
|
34
35
|
# @return [Location]
|
35
36
|
#
|
36
37
|
def location(resource_class, opts = {})
|
37
|
-
opts.reverse_merge! options
|
38
|
+
opts.reverse_merge! self.options
|
38
39
|
|
39
40
|
action = opts[:action] || :list
|
40
41
|
|
41
|
-
path = if opts[:path]
|
42
|
+
path = if Hash === opts[:path] && opts[:path].has_key?(action)
|
42
43
|
opts[:path].fetch(action)
|
43
44
|
else
|
44
|
-
path = if opts[:path]
|
45
|
+
path = if Hash === opts[:path]
|
45
46
|
opts[:path][:all].to_s
|
46
47
|
else
|
47
48
|
opts[:path].to_s
|
@@ -58,6 +59,7 @@ module Acfs
|
|
58
59
|
end
|
59
60
|
|
60
61
|
class << self
|
62
|
+
|
61
63
|
# @api public
|
62
64
|
#
|
63
65
|
# @overload identity()
|
@@ -81,7 +83,7 @@ module Acfs
|
|
81
83
|
#
|
82
84
|
def base_url
|
83
85
|
unless (base = Acfs::Configuration.current.locate identity)
|
84
|
-
raise ArgumentError
|
86
|
+
raise ArgumentError, "#{identity} not configured. Add `locate '#{identity.to_s.underscore}', 'http://service.url/'` to your configuration."
|
85
87
|
end
|
86
88
|
|
87
89
|
base.to_s
|
@@ -1,7 +1,6 @@
|
|
1
|
-
require 'acfs/service/middleware/stack'
|
2
|
-
|
3
1
|
module Acfs
|
4
2
|
class Service
|
3
|
+
|
5
4
|
# Module providing all function to register middlewares
|
6
5
|
# on services and process queued request through the
|
7
6
|
# middleware stack.
|
@@ -17,25 +16,28 @@ module Acfs
|
|
17
16
|
end
|
18
17
|
|
19
18
|
module ClassMethods
|
20
|
-
|
21
|
-
#
|
19
|
+
|
20
|
+
# @api public
|
22
21
|
#
|
23
|
-
#
|
22
|
+
# Register a new middleware to be used for this service.
|
24
23
|
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
24
|
+
# @example
|
25
|
+
# class MyService < Acfs::Service
|
26
|
+
# self.base_url = 'http://my.srv'
|
27
|
+
# use Acfs::Middleware::JsonDecoder
|
28
|
+
# end
|
30
29
|
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
# @return [undefined]
|
30
|
+
# @param [Class] klass Middleware class to instantiate and append to middleware stack.
|
31
|
+
# @param [Hash, Object] options Options to delegate to middleware class initializer.
|
32
|
+
# @return [undefined]
|
35
33
|
#
|
36
|
-
def use(klass,
|
37
|
-
|
38
|
-
|
34
|
+
def use(klass, options = {})
|
35
|
+
@middlewares ||= []
|
36
|
+
|
37
|
+
return false if @middlewares.include? klass
|
38
|
+
|
39
|
+
@middlewares << klass
|
40
|
+
@middleware = klass.new(middleware, options)
|
39
41
|
end
|
40
42
|
|
41
43
|
# @api private
|
@@ -45,11 +47,19 @@ module Acfs
|
|
45
47
|
# @return [#call]
|
46
48
|
#
|
47
49
|
def middleware
|
48
|
-
@middleware ||=
|
50
|
+
@middleware ||= proc { |request| request}
|
49
51
|
end
|
50
52
|
|
51
|
-
# @
|
52
|
-
|
53
|
+
# @api public
|
54
|
+
#
|
55
|
+
# Clear all registered middlewares.
|
56
|
+
#
|
57
|
+
# @return [undefined]
|
58
|
+
#
|
59
|
+
def clear
|
60
|
+
@middleware = nil
|
61
|
+
@middlewares = []
|
62
|
+
end
|
53
63
|
end
|
54
64
|
end
|
55
65
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module Acfs
|
2
|
+
|
2
3
|
# Acfs SingletonResources
|
3
4
|
#
|
4
5
|
# Usage explanation:
|
@@ -13,6 +14,7 @@ module Acfs
|
|
13
14
|
# always only a single instance of the resource is being returned
|
14
15
|
#
|
15
16
|
class SingletonResource < Acfs::Resource
|
17
|
+
|
16
18
|
# @api public
|
17
19
|
#
|
18
20
|
# Destroy resource by sending a DELETE request.
|
data/lib/acfs/stub.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'rack/utils'
|
2
2
|
|
3
3
|
module Acfs
|
4
|
+
|
4
5
|
# Global handler for stubbing resources.
|
5
6
|
#
|
6
7
|
class Stub
|
@@ -13,7 +14,7 @@ module Acfs
|
|
13
14
|
|
14
15
|
@opts[:with].stringify_keys! if @opts[:with].is_a? Hash
|
15
16
|
@opts[:return].stringify_keys! if @opts[:return].is_a? Hash
|
16
|
-
@opts[:return].map! {|h| h.stringify_keys! if h.is_a? Hash } if @opts[:return].is_a? Array
|
17
|
+
@opts[:return].map! { |h| h.stringify_keys! if h.is_a? Hash } if @opts[:return].is_a? Array
|
17
18
|
end
|
18
19
|
|
19
20
|
def accept?(op)
|
@@ -21,21 +22,14 @@ module Acfs
|
|
21
22
|
|
22
23
|
params = op.full_params.stringify_keys
|
23
24
|
data = op.data.stringify_keys
|
24
|
-
|
25
|
-
|
26
|
-
return true if with.nil?
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
return true if with.reject {|_, v| v.nil? } == data.reject {|_, v| v.nil? }
|
33
|
-
false
|
34
|
-
when :inclusion
|
35
|
-
with.each_pair.all? do |k, v|
|
36
|
-
(params.key?(k) && params[k] == v) || (data.key?(k) && data[k] == v)
|
37
|
-
end
|
38
|
-
end
|
25
|
+
|
26
|
+
return true if opts[:with] == params || data == opts[:with]
|
27
|
+
return true if (opts[:with].nil? && params.empty? && data.empty?)
|
28
|
+
|
29
|
+
return true if opts[:with].reject { |k, v| v.nil? } == params.reject { |k, v| v.nil? }
|
30
|
+
return true if opts[:with].reject { |k, v| v.nil? } == data.reject { |k, v| v.nil? }
|
31
|
+
|
32
|
+
false
|
39
33
|
end
|
40
34
|
|
41
35
|
def calls
|
@@ -56,20 +50,17 @@ module Acfs
|
|
56
50
|
if err
|
57
51
|
raise_error op, err, opts[:return]
|
58
52
|
elsif data
|
59
|
-
data = data.call(op) if data.respond_to?(:call)
|
60
|
-
|
61
53
|
response = Acfs::Response.new op.request,
|
62
|
-
|
63
|
-
|
64
|
-
|
54
|
+
headers: opts[:headers] || {},
|
55
|
+
status: opts[:status] || 200,
|
56
|
+
data: data || {}
|
65
57
|
op.call data, response
|
66
58
|
else
|
67
|
-
raise ArgumentError
|
59
|
+
raise ArgumentError, 'Unsupported stub.'
|
68
60
|
end
|
69
61
|
end
|
70
62
|
|
71
63
|
private
|
72
|
-
|
73
64
|
def raise_error(op, name, data)
|
74
65
|
raise name if name.is_a? Class
|
75
66
|
data.stringify_keys! if data.respond_to? :stringify_keys!
|
@@ -78,12 +69,13 @@ module Acfs
|
|
78
69
|
end
|
79
70
|
|
80
71
|
class << self
|
72
|
+
|
81
73
|
# Stub a resource with given handler block. An already created handler
|
82
74
|
# for same resource class will be overridden.
|
83
75
|
#
|
84
|
-
def resource(klass, action, opts = {}, &
|
76
|
+
def resource(klass, action, opts = {}, &block)
|
85
77
|
action = action.to_sym
|
86
|
-
raise ArgumentError
|
78
|
+
raise ArgumentError, "Unknown action `#{action}`." unless ACTIONS.include? action
|
87
79
|
|
88
80
|
Stub.new(opts).tap do |stub|
|
89
81
|
stubs[klass] ||= {}
|
@@ -104,11 +96,11 @@ module Acfs
|
|
104
96
|
@enabled ||= false
|
105
97
|
end
|
106
98
|
|
107
|
-
def enable
|
99
|
+
def enable;
|
108
100
|
@enabled = true
|
109
101
|
end
|
110
102
|
|
111
|
-
def disable
|
103
|
+
def disable;
|
112
104
|
@enabled = false
|
113
105
|
end
|
114
106
|
|
@@ -126,7 +118,7 @@ module Acfs
|
|
126
118
|
return false unless (classes = stubs[op.resource])
|
127
119
|
return false unless (stubs = classes[op.action])
|
128
120
|
|
129
|
-
accepted_stubs = stubs.select {|stub| stub.accept? op }
|
121
|
+
accepted_stubs = stubs.select { |stub| stub.accept? op }
|
130
122
|
|
131
123
|
raise AmbiguousStubError.new stubs: accepted_stubs, operation: op if accepted_stubs.size > 1
|
132
124
|
|
@@ -150,9 +142,8 @@ module Acfs
|
|
150
142
|
end
|
151
143
|
|
152
144
|
private
|
153
|
-
|
154
145
|
def pretty_print
|
155
|
-
out =
|
146
|
+
out = String.new
|
156
147
|
stubs.each do |klass, actions|
|
157
148
|
out << ' ' << klass.name << ":\n"
|
158
149
|
actions.each do |action, stubs|
|
data/lib/acfs/util.rb
CHANGED
data/lib/acfs/version.rb
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
module Acfs
|
2
2
|
module VERSION
|
3
|
-
MAJOR =
|
4
|
-
MINOR =
|
3
|
+
MAJOR = 1
|
4
|
+
MINOR = 0
|
5
5
|
PATCH = 0
|
6
|
-
STAGE =
|
6
|
+
STAGE = 'dev'
|
7
7
|
|
8
8
|
STRING = [MAJOR, MINOR, PATCH, STAGE].reject(&:nil?).join('.')
|
9
9
|
|
10
|
-
def self.to_s
|
11
|
-
STRING
|
12
|
-
end
|
10
|
+
def self.to_s; STRING end
|
13
11
|
end
|
14
12
|
end
|
@@ -5,24 +5,16 @@ describe Acfs::Adapter::Typhoeus do
|
|
5
5
|
before { WebMock.allow_net_connect! }
|
6
6
|
|
7
7
|
it 'raises an error' do
|
8
|
-
request1 = Acfs::Request.new 'http://altimos.de/404.1' do |
|
8
|
+
request1 = Acfs::Request.new 'http://altimos.de/404.1' do |rsp|
|
9
9
|
raise '404-1'
|
10
10
|
end
|
11
|
-
request2 = Acfs::Request.new 'http://altimos.de/404.2' do |
|
11
|
+
request2 = Acfs::Request.new 'http://altimos.de/404.2' do |rsp|
|
12
12
|
raise '404-2'
|
13
13
|
end
|
14
14
|
adapter.queue request1
|
15
15
|
adapter.queue request2
|
16
16
|
|
17
|
-
expect
|
18
|
-
expect
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'passes arguments to typhoeus hydra' do
|
22
|
-
value = {key: 1, key2: 2}
|
23
|
-
|
24
|
-
expect(::Typhoeus::Hydra).to receive(:new).with(value)
|
25
|
-
|
26
|
-
described_class.new(**value).send :hydra
|
17
|
+
expect{ adapter.start }.to raise_error /404\-[12]/
|
18
|
+
expect{ adapter.start }.to_not raise_error
|
27
19
|
end
|
28
20
|
end
|