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.
Files changed (90) hide show
  1. checksums.yaml +13 -5
  2. data/CHANGELOG.md +0 -80
  3. data/README.md +9 -8
  4. data/acfs.gemspec +7 -7
  5. data/lib/acfs.rb +5 -7
  6. data/lib/acfs/adapter/base.rb +2 -0
  7. data/lib/acfs/adapter/typhoeus.rb +13 -17
  8. data/lib/acfs/collections/paginatable.rb +10 -10
  9. data/lib/acfs/configuration.rb +5 -4
  10. data/lib/acfs/errors.rb +9 -10
  11. data/lib/acfs/global.rb +7 -16
  12. data/lib/acfs/location.rb +11 -11
  13. data/lib/acfs/middleware/base.rb +2 -1
  14. data/lib/acfs/middleware/json_decoder.rb +16 -0
  15. data/lib/acfs/middleware/json_encoder.rb +20 -0
  16. data/lib/acfs/middleware/logger.rb +2 -0
  17. data/lib/acfs/middleware/msgpack_decoder.rb +26 -0
  18. data/lib/acfs/middleware/msgpack_encoder.rb +19 -0
  19. data/lib/acfs/middleware/print.rb +2 -0
  20. data/lib/acfs/operation.rb +5 -5
  21. data/lib/acfs/request.rb +4 -4
  22. data/lib/acfs/request/callbacks.rb +3 -2
  23. data/lib/acfs/resource.rb +2 -2
  24. data/lib/acfs/resource/attributes.rb +38 -11
  25. data/lib/acfs/resource/attributes/base.rb +19 -10
  26. data/lib/acfs/resource/attributes/boolean.rb +8 -10
  27. data/lib/acfs/resource/attributes/date_time.rb +9 -6
  28. data/lib/acfs/resource/attributes/float.rb +5 -11
  29. data/lib/acfs/resource/attributes/integer.rb +5 -7
  30. data/lib/acfs/resource/attributes/list.rb +6 -13
  31. data/lib/acfs/resource/attributes/string.rb +5 -3
  32. data/lib/acfs/resource/attributes/uuid.rb +17 -8
  33. data/lib/acfs/resource/dirty.rb +15 -3
  34. data/lib/acfs/resource/loadable.rb +1 -0
  35. data/lib/acfs/resource/locatable.rb +4 -0
  36. data/lib/acfs/resource/operational.rb +2 -0
  37. data/lib/acfs/resource/persistence.rb +17 -17
  38. data/lib/acfs/resource/query_methods.rb +7 -8
  39. data/lib/acfs/resource/service.rb +2 -0
  40. data/lib/acfs/resource/validation.rb +4 -4
  41. data/lib/acfs/response.rb +2 -1
  42. data/lib/acfs/response/formats.rb +3 -2
  43. data/lib/acfs/response/status.rb +5 -3
  44. data/lib/acfs/runner.rb +11 -21
  45. data/lib/acfs/service.rb +6 -4
  46. data/lib/acfs/service/middleware.rb +30 -20
  47. data/lib/acfs/singleton_resource.rb +2 -0
  48. data/lib/acfs/stub.rb +21 -30
  49. data/lib/acfs/util.rb +1 -1
  50. data/lib/acfs/version.rb +4 -6
  51. data/spec/acfs/adapter/typhoeus_spec.rb +4 -12
  52. data/spec/acfs/collection_spec.rb +33 -45
  53. data/spec/acfs/configuration_spec.rb +1 -9
  54. data/spec/acfs/global_spec.rb +3 -21
  55. data/spec/acfs/middleware/json_decoder_spec.rb +45 -0
  56. data/spec/acfs/middleware/msgpack_decoder_spec.rb +36 -0
  57. data/spec/acfs/request/callbacks_spec.rb +8 -8
  58. data/spec/acfs/request_spec.rb +5 -5
  59. data/spec/acfs/resource/attributes/boolean_spec.rb +9 -40
  60. data/spec/acfs/resource/attributes/date_time_spec.rb +35 -29
  61. data/spec/acfs/resource/attributes/float_spec.rb +9 -48
  62. data/spec/acfs/resource/attributes/list_spec.rb +19 -43
  63. data/spec/acfs/resource/attributes/uuid_spec.rb +54 -31
  64. data/spec/acfs/resource/attributes_spec.rb +31 -17
  65. data/spec/acfs/resource/locatable_spec.rb +2 -2
  66. data/spec/acfs/resource/persistance_spec.rb +34 -65
  67. data/spec/acfs/resource/query_methods_spec.rb +90 -97
  68. data/spec/acfs/resource/validation_spec.rb +5 -4
  69. data/spec/acfs/response/formats_spec.rb +4 -4
  70. data/spec/acfs/response/status_spec.rb +1 -1
  71. data/spec/acfs/runner_spec.rb +3 -28
  72. data/spec/acfs/service/middleware_spec.rb +20 -4
  73. data/spec/acfs/service_spec.rb +5 -3
  74. data/spec/acfs/singleton_resource_spec.rb +2 -1
  75. data/spec/acfs/stub_spec.rb +22 -137
  76. data/spec/acfs_spec.rb +19 -22
  77. data/spec/spec_helper.rb +2 -3
  78. data/spec/support/service.rb +6 -10
  79. data/spec/support/shared/find_callbacks.rb +7 -7
  80. metadata +36 -43
  81. data/lib/acfs/middleware/json.rb +0 -27
  82. data/lib/acfs/middleware/msgpack.rb +0 -30
  83. data/lib/acfs/middleware/serializer.rb +0 -39
  84. data/lib/acfs/resource/attributes/dict.rb +0 -37
  85. data/lib/acfs/service/middleware/stack.rb +0 -63
  86. data/spec/acfs/middleware/json_spec.rb +0 -63
  87. data/spec/acfs/middleware/msgpack_spec.rb +0 -60
  88. data/spec/acfs/operation_spec.rb +0 -10
  89. data/spec/acfs/resource/attributes/dict_spec.rb +0 -75
  90. data/spec/acfs/resource/attributes/integer_spec.rb +0 -34
@@ -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
- # delegate :status, :status_message, :success?, :modified?, :timed_out?,
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[:json]
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
 
@@ -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
- # return response.response_code unless response.nil?
12
- # 0
13
+ #return response.response_code unless response.nil?
14
+ #0
13
15
  end
14
- alias_method :code, :status_code
16
+ alias :code :status_code
15
17
 
16
18
  # Return true if response was successful indicated by
17
19
  # response status code.
@@ -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
- start_all
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? && Acfs::Stub.stubbed(op)
90
- req = op.service.prepare op.request
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
@@ -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].is_a?(Hash) && opts[:path].key?(action)
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].is_a?(Hash)
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.new "#{identity} not configured. Add `locate '#{identity.to_s.underscore}', 'http://service.url/'` to your configuration."
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
- # @!method use(klass, *args, &block)
21
- # @api public
19
+
20
+ # @api public
22
21
  #
23
- # Register a new middleware to be used for this service.
22
+ # Register a new middleware to be used for this service.
24
23
  #
25
- # @example
26
- # class MyService < Acfs::Service
27
- # self.base_url = 'http://my.srv'
28
- # use Acfs::Middleware::JSON
29
- # end
24
+ # @example
25
+ # class MyService < Acfs::Service
26
+ # self.base_url = 'http://my.srv'
27
+ # use Acfs::Middleware::JsonDecoder
28
+ # end
30
29
  #
31
- # @param [Class] klass Middleware class to append
32
- # @param [Array<Object>] args Arguments passed to klass initialize
33
- # @param [Proc] block Block passed to klass initialize
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, *args, &block)
37
- # Backward compatible behavior
38
- middleware.insert(0, klass, *args, &block)
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 ||= Stack.new
50
+ @middleware ||= proc { |request| request}
49
51
  end
50
52
 
51
- # @deprecated
52
- delegate :clear, to: :middleware
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.
@@ -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
- with = opts[:with]
25
-
26
- return true if with.nil?
27
-
28
- case opts.fetch(:match, :inclusion)
29
- when :legacy
30
- return true if with.empty? && params.empty? && data.empty?
31
- return true if with.reject {|_, v| v.nil? } == params.reject {|_, v| v.nil? }
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
- headers: opts[:headers] || {},
63
- status: opts[:status] || 200,
64
- data: data || {}
54
+ headers: opts[:headers] || {},
55
+ status: opts[:status] || 200,
56
+ data: data || {}
65
57
  op.call data, response
66
58
  else
67
- raise ArgumentError.new 'Unsupported stub.'
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 = {}, &_block)
76
+ def resource(klass, action, opts = {}, &block)
85
77
  action = action.to_sym
86
- raise ArgumentError.new "Unknown action `#{action}`." unless ACTIONS.include? action
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|
@@ -7,7 +7,7 @@ module Acfs
7
7
  end
8
8
 
9
9
  def __invoke__
10
- __callbacks__.each {|c| c.call self }
10
+ __callbacks__.each{|c| c.call self}
11
11
  end
12
12
  end
13
13
 
@@ -1,14 +1,12 @@
1
1
  module Acfs
2
2
  module VERSION
3
- MAJOR = 0
4
- MINOR = 50
3
+ MAJOR = 1
4
+ MINOR = 0
5
5
  PATCH = 0
6
- STAGE = nil
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 |_rsp|
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 |_rsp|
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 { adapter.start }.to raise_error(/404\-[12]/)
18
- expect { adapter.start }.to_not raise_error
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