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
  class Acfs::Resource
2
4
  # @api private
3
5
  #
@@ -11,7 +13,6 @@ class Acfs::Resource
11
13
  extend ActiveSupport::Concern
12
14
  delegate :operation, to: :'self.class'
13
15
 
14
- #
15
16
  module ClassMethods
16
17
  # Invoke CRUD operation.
17
18
  def operation(action, opts = {}, &block)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Acfs::Resource
2
4
  #
3
5
  # Allow to track the persistence state of a model.
@@ -40,7 +42,7 @@ class Acfs::Resource
40
42
  def new?
41
43
  !loaded?
42
44
  end
43
- alias_method :new_record?, :new?
45
+ alias new_record? new?
44
46
 
45
47
  # @api public
46
48
  #
@@ -86,9 +88,9 @@ class Acfs::Resource
86
88
  operation((new? ? :create : :update), opts) do |data|
87
89
  update_with data
88
90
  end
89
- rescue ::Acfs::InvalidResource => err
90
- self.remote_errors = err.errors
91
- raise err
91
+ rescue ::Acfs::InvalidResource => e
92
+ self.remote_errors = e.errors
93
+ raise e
92
94
  end
93
95
 
94
96
  # @api public
@@ -242,8 +244,6 @@ class Acfs::Resource
242
244
  end
243
245
  end
244
246
 
245
- private
246
-
247
247
  def update_with(data)
248
248
  self.attributes = data
249
249
  loaded!
@@ -251,6 +251,7 @@ class Acfs::Resource
251
251
 
252
252
  def check_loaded!(opts = {})
253
253
  return if loaded? || opts[:force]
254
+
254
255
  raise ::Acfs::ResourceNotLoaded.new resource: self
255
256
  end
256
257
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Acfs::Resource
2
4
  # Methods providing the query interface for finding resouces.
3
5
  #
@@ -14,7 +16,6 @@ class Acfs::Resource
14
16
  module QueryMethods
15
17
  extend ActiveSupport::Concern
16
18
 
17
- #
18
19
  module ClassMethods
19
20
  # @api public
20
21
  #
@@ -89,7 +90,7 @@ class Acfs::Resource
89
90
 
90
91
  collection
91
92
  end
92
- alias_method :where, :all
93
+ alias where all
93
94
 
94
95
  # @api public
95
96
  #
@@ -140,7 +141,7 @@ class Acfs::Resource
140
141
  raise Acfs::ResourceNotFound.new message: 'Received erroneous ' \
141
142
  "response: no `#{name}` with params #{params} found"
142
143
  end
143
- block.call m unless block.nil?
144
+ block&.call m
144
145
  end
145
146
  end
146
147
 
@@ -249,6 +250,7 @@ class Acfs::Resource
249
250
 
250
251
  def resource_class_lookup(type)
251
252
  return self if type.nil?
253
+
252
254
  klass = type.camelize.constantize
253
255
 
254
256
  unless klass <= self
@@ -256,7 +258,7 @@ class Acfs::Resource
256
258
  end
257
259
 
258
260
  klass
259
- rescue NameError, NoMethodError
261
+ rescue NameError
260
262
  raise Acfs::ResourceTypeError.new type_name: type, base_class: self
261
263
  end
262
264
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Acfs::Resource
2
4
  # Included by Acfs::Model. Allows to configure the service
3
5
  # a resource belongs to.
@@ -5,7 +7,6 @@ class Acfs::Resource
5
7
  module Service
6
8
  extend ActiveSupport::Concern
7
9
 
8
- #
9
10
  module ClassMethods
10
11
  # @api public
11
12
  #
@@ -35,6 +36,7 @@ class Acfs::Resource
35
36
  #
36
37
  def service(klass = nil, options = {})
37
38
  return (@service = klass.new options) if klass
39
+
38
40
  @service || superclass.service
39
41
  end
40
42
  end
@@ -1,12 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Acfs::Resource
2
- #
3
4
  module Validation
4
- def valid?(*args)
5
- super
6
- remote_errors.each {|f, e| errors.add f, e }
7
- errors.empty?
8
- end
9
-
10
5
  def remote_errors
11
6
  @remote_errors ||= ActiveModel::Errors.new self
12
7
  end
@@ -31,7 +26,24 @@ class Acfs::Resource
31
26
  unless valid?(new? ? :create : :save)
32
27
  raise ::Acfs::InvalidResource.new resource: self, errors: errors.to_a
33
28
  end
29
+
34
30
  super
35
31
  end
32
+
33
+ if ::ActiveModel.version >= Gem::Version.new('6.1')
34
+ def valid?(*args)
35
+ super
36
+
37
+ remote_errors.each {|e| errors.add(e.attribute, e.message) }
38
+ errors.empty?
39
+ end
40
+ else
41
+ def valid?(*args)
42
+ super
43
+
44
+ remote_errors.each {|f, e| errors.add(f, e) }
45
+ errors.empty?
46
+ end
47
+ end
36
48
  end
37
49
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'acfs/response/formats'
2
4
  require 'acfs/response/status'
3
5
  require 'active_support/core_ext/module/delegation'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'action_dispatch'
2
4
 
3
5
  module Acfs
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs
2
4
  class Response
3
5
  # Method to fetch information about response status.
@@ -11,7 +13,7 @@ module Acfs
11
13
  # return response.response_code unless response.nil?
12
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,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'acfs'
2
4
 
3
5
  RSpec.configure do |config|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'acfs/service/middleware'
2
4
 
3
5
  module Acfs
@@ -59,7 +61,7 @@ module Acfs
59
61
 
60
62
  enqueue_operations
61
63
  start_all
62
- rescue
64
+ rescue StandardError
63
65
  queue.clear
64
66
  raise
65
67
  end
@@ -87,10 +89,13 @@ module Acfs
87
89
 
88
90
  def op_request(op)
89
91
  return if Acfs::Stub.enabled? && Acfs::Stub.stubbed(op)
92
+
90
93
  req = op.service.prepare op.request
91
94
  return unless req.is_a? Acfs::Request
95
+
92
96
  req = prepare req
93
97
  return unless req.is_a? Acfs::Request
98
+
94
99
  yield req
95
100
  end
96
101
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'acfs/service/middleware'
2
4
 
3
5
  module Acfs
@@ -38,21 +40,27 @@ module Acfs
38
40
 
39
41
  action = opts[:action] || :list
40
42
 
41
- path = if opts[:path].is_a?(Hash) && opts[:path].key?(action)
42
- opts[:path].fetch(action)
43
- else
44
- path = if opts[:path].is_a?(Hash)
45
- opts[:path][:all].to_s
46
- else
47
- opts[:path].to_s
48
- end
43
+ path = begin
44
+ if opts[:path].is_a?(Hash) && opts[:path].key?(action)
45
+ opts[:path].fetch(action)
46
+ else
47
+ path = if opts[:path].is_a?(Hash)
48
+ opts[:path][:all].to_s
49
+ else
50
+ opts[:path].to_s
51
+ end
49
52
 
50
- path = (resource_class.name || 'class').pluralize.underscore if path.blank?
53
+ if path.blank?
54
+ path = (resource_class.name || 'class').pluralize.underscore
55
+ end
51
56
 
52
- resource_class.location_default_path(action, path.strip)
53
- end
57
+ resource_class.location_default_path(action, path.strip)
58
+ end
59
+ end
54
60
 
55
- raise ArgumentError.new "Location for `#{action}' explicit disabled by set to nil." if path.nil?
61
+ if path.nil?
62
+ raise ArgumentError.new "Location for `#{action}' explicit disabled by set to nil."
63
+ end
56
64
 
57
65
  Location.new [self.class.base_url.to_s, path.to_s].join('/')
58
66
  end
@@ -81,7 +89,10 @@ module Acfs
81
89
  #
82
90
  def base_url
83
91
  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."
92
+ raise ArgumentError.new \
93
+ "#{identity} not configured. Add `locate '" \
94
+ "#{identity.to_s.underscore}', 'http://service.url/'` " \
95
+ 'to your configuration.'
85
96
  end
86
97
 
87
98
  base.to_s
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'acfs/service/middleware/stack'
2
4
 
3
5
  module Acfs
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs
2
4
  class Service
3
5
  module Middleware
@@ -5,7 +7,7 @@ module Acfs
5
7
  include Enumerable
6
8
 
7
9
  MUTEX = Mutex.new
8
- IDENTITY = -> (i) { i }
10
+ IDENTITY = ->(i) { i }
9
11
 
10
12
  attr_reader :middlewares
11
13
 
@@ -41,7 +43,7 @@ module Acfs
41
43
  next_middleware.call(klass.call(env, *args))
42
44
  end
43
45
  else
44
- fail "Invalid middleware, doesn't respond to `call`: #{klass.inspect}"
46
+ raise "Invalid middleware, doesn't respond to `call`: #{klass.inspect}"
45
47
  end
46
48
  end
47
49
  end
@@ -51,7 +53,7 @@ module Acfs
51
53
  end
52
54
 
53
55
  def each
54
- middlewares.each { |x| yield x.first }
56
+ middlewares.each {|x| yield x.first }
55
57
  end
56
58
 
57
59
  def clear
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Acfs
2
4
  # Acfs SingletonResources
3
5
  #
@@ -71,8 +73,8 @@ module Acfs
71
73
  def all
72
74
  raise ::Acfs::UnsupportedOperation.new
73
75
  end
74
- alias_method :find_by, :all
75
- alias_method :find_by!, :all
76
+ alias find_by all
77
+ alias find_by! all
76
78
 
77
79
  # @api private
78
80
  def location_default_path(_, path)
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rack/utils'
2
4
 
3
5
  module Acfs
4
6
  # Global handler for stubbing resources.
5
7
  #
6
8
  class Stub
7
- ACTIONS = [:read, :create, :update, :delete, :list]
9
+ ACTIONS = %i[read create update delete list].freeze
8
10
 
9
11
  attr_reader :opts
10
12
 
@@ -13,7 +15,10 @@ module Acfs
13
15
 
14
16
  @opts[:with].stringify_keys! if @opts[:with].is_a? Hash
15
17
  @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
18
+
19
+ if @opts[:return].is_a?(Array) # rubocop:disable Style/GuardClause
20
+ @opts[:return].map! {|h| h.stringify_keys! if h.is_a? Hash }
21
+ end
17
22
  end
18
23
 
19
24
  def accept?(op)
@@ -28,8 +33,13 @@ module Acfs
28
33
  case opts.fetch(:match, :inclusion)
29
34
  when :legacy
30
35
  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? }
36
+ if with.reject {|_, v| v.nil? } == params.reject {|_, v| v.nil? }
37
+ return true
38
+ end
39
+ if with.reject {|_, v| v.nil? } == data.reject {|_, v| v.nil? }
40
+ return true
41
+ end
42
+
33
43
  false
34
44
  when :inclusion
35
45
  with.each_pair.all? do |k, v|
@@ -43,7 +53,8 @@ module Acfs
43
53
  end
44
54
 
45
55
  def called?(count = nil)
46
- count = count.count if count.respond_to? :count # For `5.times` Enumerators
56
+ count = count.count if count.respond_to?(:count)
57
+
47
58
  count.nil? ? calls.any? : calls.size == count
48
59
  end
49
60
 
@@ -60,8 +71,8 @@ module Acfs
60
71
 
61
72
  response = Acfs::Response.new op.request,
62
73
  headers: opts[:headers] || {},
63
- status: opts[:status] || 200,
64
- data: data || {}
74
+ status: opts[:status] || 200,
75
+ data: data || {}
65
76
  op.call data, response
66
77
  else
67
78
  raise ArgumentError.new 'Unsupported stub.'
@@ -72,6 +83,7 @@ module Acfs
72
83
 
73
84
  def raise_error(op, name, data)
74
85
  raise name if name.is_a? Class
86
+
75
87
  data.stringify_keys! if data.respond_to? :stringify_keys!
76
88
 
77
89
  op.handle_failure ::Acfs::Response.new op.request, status: Rack::Utils.status_code(name), data: data
@@ -83,7 +95,9 @@ module Acfs
83
95
  #
84
96
  def resource(klass, action, opts = {}, &_block)
85
97
  action = action.to_sym
86
- raise ArgumentError.new "Unknown action `#{action}`." unless ACTIONS.include? action
98
+ unless ACTIONS.include? action
99
+ raise ArgumentError.new "Unknown action `#{action}`."
100
+ end
87
101
 
88
102
  Stub.new(opts).tap do |stub|
89
103
  stubs[klass] ||= {}
@@ -128,7 +142,9 @@ module Acfs
128
142
 
129
143
  accepted_stubs = stubs.select {|stub| stub.accept? op }
130
144
 
131
- raise AmbiguousStubError.new stubs: accepted_stubs, operation: op if accepted_stubs.size > 1
145
+ if accepted_stubs.size > 1
146
+ raise AmbiguousStubError.new stubs: accepted_stubs, operation: op
147
+ end
132
148
 
133
149
  accepted_stubs.first
134
150
  end
@@ -137,6 +153,7 @@ module Acfs
137
153
  stub = stub_for op
138
154
  unless stub
139
155
  return false if allow_requests?
156
+
140
157
  raise RealRequestsNotAllowedError.new <<-MSG.strip.gsub(/^[ ]{12}/, '')
141
158
  No stub found for `#{op.action}' on `#{op.resource.name}' with params `#{op.full_params.inspect}', data `#{op.data.inspect}' and id `#{op.id}'.
142
159
 
@@ -159,8 +176,12 @@ module Acfs
159
176
  stubs.each do |stub|
160
177
  out << " #{action}"
161
178
  out << " with #{stub.opts[:with].inspect}" if stub.opts[:with]
162
- out << " and return #{stub.opts[:return].inspect}" if stub.opts[:return]
163
- out << " and raise #{stub.opts[:raise].inspect}" if stub.opts[:raise]
179
+ if stub.opts[:return]
180
+ out << " and return #{stub.opts[:return].inspect}"
181
+ end
182
+ if stub.opts[:raise]
183
+ out << " and raise #{stub.opts[:raise].inspect}"
184
+ end
164
185
  out << "\n"
165
186
  end
166
187
  end