acfs 1.0.0.dev.1.b305 → 1.0.0

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 (89) hide show
  1. checksums.yaml +5 -13
  2. data/CHANGELOG.md +64 -0
  3. data/README.md +2 -2
  4. data/acfs.gemspec +4 -4
  5. data/lib/acfs.rb +7 -5
  6. data/lib/acfs/adapter/base.rb +0 -2
  7. data/lib/acfs/adapter/typhoeus.rb +17 -13
  8. data/lib/acfs/collections/paginatable.rb +10 -10
  9. data/lib/acfs/configuration.rb +4 -5
  10. data/lib/acfs/errors.rb +10 -9
  11. data/lib/acfs/global.rb +16 -7
  12. data/lib/acfs/location.rb +11 -11
  13. data/lib/acfs/middleware/base.rb +1 -2
  14. data/lib/acfs/middleware/json.rb +27 -0
  15. data/lib/acfs/middleware/logger.rb +0 -2
  16. data/lib/acfs/middleware/msgpack.rb +30 -0
  17. data/lib/acfs/middleware/print.rb +0 -2
  18. data/lib/acfs/middleware/serializer.rb +39 -0
  19. data/lib/acfs/operation.rb +5 -5
  20. data/lib/acfs/request.rb +4 -4
  21. data/lib/acfs/request/callbacks.rb +2 -3
  22. data/lib/acfs/resource.rb +2 -2
  23. data/lib/acfs/resource/attributes.rb +10 -37
  24. data/lib/acfs/resource/attributes/base.rb +10 -19
  25. data/lib/acfs/resource/attributes/boolean.rb +10 -8
  26. data/lib/acfs/resource/attributes/date_time.rb +6 -9
  27. data/lib/acfs/resource/attributes/dict.rb +37 -0
  28. data/lib/acfs/resource/attributes/float.rb +11 -5
  29. data/lib/acfs/resource/attributes/integer.rb +7 -5
  30. data/lib/acfs/resource/attributes/list.rb +13 -6
  31. data/lib/acfs/resource/attributes/string.rb +3 -5
  32. data/lib/acfs/resource/attributes/uuid.rb +8 -17
  33. data/lib/acfs/resource/loadable.rb +0 -1
  34. data/lib/acfs/resource/locatable.rb +0 -4
  35. data/lib/acfs/resource/operational.rb +0 -2
  36. data/lib/acfs/resource/persistence.rb +17 -17
  37. data/lib/acfs/resource/query_methods.rb +3 -5
  38. data/lib/acfs/resource/service.rb +0 -2
  39. data/lib/acfs/resource/validation.rb +0 -2
  40. data/lib/acfs/response.rb +1 -2
  41. data/lib/acfs/response/formats.rb +1 -2
  42. data/lib/acfs/response/status.rb +3 -5
  43. data/lib/acfs/runner.rb +21 -11
  44. data/lib/acfs/service.rb +4 -6
  45. data/lib/acfs/service/middleware.rb +20 -30
  46. data/lib/acfs/service/middleware/stack.rb +63 -0
  47. data/lib/acfs/singleton_resource.rb +0 -2
  48. data/lib/acfs/stub.rb +30 -21
  49. data/lib/acfs/util.rb +1 -1
  50. data/lib/acfs/version.rb +4 -2
  51. data/spec/acfs/adapter/typhoeus_spec.rb +12 -4
  52. data/spec/acfs/collection_spec.rb +45 -33
  53. data/spec/acfs/configuration_spec.rb +9 -1
  54. data/spec/acfs/global_spec.rb +21 -3
  55. data/spec/acfs/middleware/json_spec.rb +63 -0
  56. data/spec/acfs/middleware/msgpack_spec.rb +60 -0
  57. data/spec/acfs/operation_spec.rb +10 -0
  58. data/spec/acfs/request/callbacks_spec.rb +8 -8
  59. data/spec/acfs/request_spec.rb +5 -5
  60. data/spec/acfs/resource/attributes/boolean_spec.rb +40 -9
  61. data/spec/acfs/resource/attributes/date_time_spec.rb +29 -35
  62. data/spec/acfs/resource/attributes/dict_spec.rb +75 -0
  63. data/spec/acfs/resource/attributes/float_spec.rb +48 -9
  64. data/spec/acfs/resource/attributes/integer_spec.rb +34 -0
  65. data/spec/acfs/resource/attributes/list_spec.rb +43 -19
  66. data/spec/acfs/resource/attributes/uuid_spec.rb +31 -54
  67. data/spec/acfs/resource/attributes_spec.rb +17 -31
  68. data/spec/acfs/resource/locatable_spec.rb +2 -2
  69. data/spec/acfs/resource/persistance_spec.rb +65 -34
  70. data/spec/acfs/resource/query_methods_spec.rb +87 -87
  71. data/spec/acfs/resource/validation_spec.rb +4 -5
  72. data/spec/acfs/response/formats_spec.rb +1 -1
  73. data/spec/acfs/response/status_spec.rb +1 -1
  74. data/spec/acfs/runner_spec.rb +28 -3
  75. data/spec/acfs/service/middleware_spec.rb +4 -20
  76. data/spec/acfs/service_spec.rb +3 -5
  77. data/spec/acfs/singleton_resource_spec.rb +1 -2
  78. data/spec/acfs/stub_spec.rb +137 -22
  79. data/spec/acfs_spec.rb +22 -19
  80. data/spec/spec_helper.rb +2 -1
  81. data/spec/support/service.rb +10 -6
  82. data/spec/support/shared/find_callbacks.rb +7 -7
  83. metadata +37 -30
  84. data/lib/acfs/middleware/json_decoder.rb +0 -16
  85. data/lib/acfs/middleware/json_encoder.rb +0 -20
  86. data/lib/acfs/middleware/msgpack_decoder.rb +0 -26
  87. data/lib/acfs/middleware/msgpack_encoder.rb +0 -19
  88. data/spec/acfs/middleware/json_decoder_spec.rb +0 -45
  89. data/spec/acfs/middleware/msgpack_decoder_spec.rb +0 -36
@@ -1,5 +1,4 @@
1
1
  module Acfs::Resource::Attributes
2
-
3
2
  # @api public
4
3
  #
5
4
  # Float attribute type. Use it in your model as an attribute type:
@@ -10,16 +9,23 @@ module Acfs::Resource::Attributes
10
9
  # end
11
10
  #
12
11
  class Float < Base
13
-
14
12
  # @api public
15
13
  #
16
14
  # Cast given object to float.
17
15
  #
18
- # @param [Object] obj Object to cast.
16
+ # @param [Object] value Object to cast.
19
17
  # @return [Float] Casted object as float.
20
18
  #
21
- def cast_type(obj)
22
- Float obj
19
+ def cast_value(value)
20
+ return 0.0 if value.blank?
21
+
22
+ case value
23
+ when ::Float then value
24
+ when "Infinity" then ::Float::INFINITY
25
+ when "-Infinity" then -::Float::INFINITY
26
+ when "NaN" then ::Float::NAN
27
+ else Float(value)
28
+ end
23
29
  end
24
30
  end
25
31
  end
@@ -1,5 +1,4 @@
1
1
  module Acfs::Resource::Attributes
2
-
3
2
  # @api public
4
3
  #
5
4
  # Integer attribute type. Use it in your model as an attribute type:
@@ -10,16 +9,19 @@ module Acfs::Resource::Attributes
10
9
  # end
11
10
  #
12
11
  class Integer < Base
13
-
14
12
  # @api public
15
13
  #
16
14
  # Cast given object to integer.
17
15
  #
18
- # @param [Object] obj Object to cast.
16
+ # @param [Object] value Object to cast.
19
17
  # @return [Fixnum] Casted object as fixnum.
20
18
  #
21
- def cast_type(obj)
22
- Integer obj
19
+ def cast_value(value)
20
+ if value.blank?
21
+ 0
22
+ else
23
+ Integer(value)
24
+ end
23
25
  end
24
26
  end
25
27
  end
@@ -1,5 +1,4 @@
1
1
  module Acfs::Resource::Attributes
2
-
3
2
  # @api public
4
3
  #
5
4
  # List attribute type. Use it in your model as an attribute type:
@@ -10,18 +9,26 @@ module Acfs::Resource::Attributes
10
9
  # end
11
10
  #
12
11
  class List < Base
13
-
14
12
  # @api public
15
13
  #
16
14
  # Cast given object to a list.
17
15
  #
18
- # @param [Object] obj Object to cast.
16
+ # @param [Object] value Object to cast.
19
17
  # @return [Fixnum] Casted object as list.
20
18
  # @raise [TypeError] If object cannot be casted to a list.
21
19
  #
22
- def cast_type(obj)
23
- return obj.to_a if obj.respond_to? :to_a
24
- raise TypeError.new "Cannot cast #{obj.inspect} to array."
20
+ def cast_value(value)
21
+ return [] if value.blank?
22
+
23
+ if value.is_a?(::Array)
24
+ value
25
+ elsif value.respond_to?(:to_ary)
26
+ value.to_ary
27
+ elsif value.respond_to?(:to_a)
28
+ value.to_a
29
+ else
30
+ Array(value)
31
+ end
25
32
  end
26
33
  end
27
34
  end
@@ -1,5 +1,4 @@
1
1
  module Acfs::Resource::Attributes
2
-
3
2
  # @api public
4
3
  #
5
4
  # String attribute type. Use it in your model as
@@ -11,16 +10,15 @@ module Acfs::Resource::Attributes
11
10
  # end
12
11
  #
13
12
  class String < Base
14
-
15
13
  # @api public
16
14
  #
17
15
  # Cast given object to string.
18
16
  #
19
- # @param [Object] obj Object to cast.
17
+ # @param [Object] value Object to cast.
20
18
  # @return [String] Casted string.
21
19
  #
22
- def cast_type(obj)
23
- obj.to_s
20
+ def cast_value(value)
21
+ value.to_s
24
22
  end
25
23
  end
26
24
  end
@@ -1,5 +1,4 @@
1
1
  module Acfs::Resource::Attributes
2
-
3
2
  # @api public
4
3
  #
5
4
  # UUID attribute type. Use it in your model as an attribute type:
@@ -10,9 +9,8 @@ module Acfs::Resource::Attributes
10
9
  # end
11
10
  #
12
11
  class UUID < Base
13
-
14
12
  #
15
- REGEXP = /[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}/i
13
+ UUID_REGEXP = /[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}/i
16
14
 
17
15
  # @api public
18
16
  #
@@ -30,23 +28,16 @@ module Acfs::Resource::Attributes
30
28
  # | 4 | 4 |
31
29
  # | 5 | 12 |
32
30
  #
33
- # @param [Object] obj Object to cast.
31
+ # @param [Object] value Object to cast.
34
32
  # @return [String] Casted object as UUID.
35
33
  #
36
- def cast_type(obj)
37
- cast_string obj.to_s
38
- end
39
-
40
- private
41
-
42
- def cast_string(str)
43
- if nil_allowed? && str.blank?
44
- return nil
45
- elsif str =~ REGEXP
46
- str
34
+ def cast_value(value)
35
+ if value.blank?
36
+ nil
37
+ elsif value.to_s =~ UUID_REGEXP
38
+ value
47
39
  else
48
- raise ArgumentError.new "given String `#{str}` " \
49
- "does not look like a UUID"
40
+ raise TypeError.new "Invalid UUID: `#{value.to_s}'"
50
41
  end
51
42
  end
52
43
  end
@@ -1,5 +1,4 @@
1
1
  class Acfs::Resource
2
-
3
2
  # Provides method to check for loading state of resources.
4
3
  # A resource that is created but not yet fetched will be loaded
5
4
  # after running {Acfs::Global#run Acfs.run}.
@@ -1,5 +1,4 @@
1
1
  class Acfs::Resource
2
-
3
2
  # Provide methods for generation URLs for resources.
4
3
  #
5
4
  # @example
@@ -14,7 +13,6 @@ class Acfs::Resource
14
13
 
15
14
  #
16
15
  module ClassMethods
17
-
18
16
  # @overload url(suffix)
19
17
  # @deprecated
20
18
  # Return URL for this class of resource. Given suffix
@@ -90,8 +88,6 @@ class Acfs::Resource
90
88
  return path
91
89
  when :read, :update, :delete
92
90
  return "#{path}/:id"
93
- else
94
- nil
95
91
  end
96
92
  end
97
93
  end
@@ -1,5 +1,4 @@
1
1
  class Acfs::Resource
2
-
3
2
  # @api private
4
3
  #
5
4
  # Provide methods for creating and processing CRUD operations and
@@ -14,7 +13,6 @@ class Acfs::Resource
14
13
 
15
14
  #
16
15
  module ClassMethods
17
-
18
16
  # Invoke CRUD operation.
19
17
  def operation(action, opts = {}, &block)
20
18
  Acfs.runner.process ::Acfs::Operation.new self, action, opts, &block
@@ -8,8 +8,7 @@ class Acfs::Resource
8
8
  # @api public
9
9
  #
10
10
  # Check if the model is persisted. A model is persisted if
11
- # it is saved after being created or when it was not changed
12
- # since it was loaded.
11
+ # it is saved after being created
13
12
  #
14
13
  # @example Newly created resource:
15
14
  # user = User.new name: "John"
@@ -21,15 +20,14 @@ class Acfs::Resource
21
20
  # user2 = User.find 5
22
21
  # user2.persisted? # => true
23
22
  # user2.name = 'Amy'
24
- # user2.persisted? # => false
23
+ # user2.persisted? # => true
25
24
  # user2.save
26
25
  # user2.persisted? # => true
27
26
  #
28
- # @return [Boolean] True if resource has no changes and
29
- # is not newly created, false otherwise.
27
+ # @return [Boolean] True if resource has been saved
30
28
  #
31
29
  def persisted?
32
- !new? && !changed?
30
+ !new?
33
31
  end
34
32
 
35
33
  # @api public
@@ -174,7 +172,7 @@ class Acfs::Resource
174
172
  #
175
173
  def delete!(opts = {})
176
174
  opts[:params] ||= {}
177
- opts[:params].merge! id: id
175
+ opts[:params] = attributes_for_url(:delete).merge opts[:params]
178
176
 
179
177
  operation :delete, opts do |data|
180
178
  update_with data
@@ -182,9 +180,14 @@ class Acfs::Resource
182
180
  end
183
181
  end
184
182
 
185
- #
186
- module ClassMethods
183
+ private
187
184
 
185
+ def attributes_for_url(action)
186
+ arguments_for_url = self.class.location(action: action).arguments
187
+ attributes.slice(*arguments_for_url)
188
+ end
189
+
190
+ module ClassMethods
188
191
  # @api public
189
192
  #
190
193
  # Create a new resource sending given data. If resource cannot be
@@ -208,10 +211,8 @@ class Acfs::Resource
208
211
  # will be overridden with provided data hash.
209
212
  # @see #create
210
213
  #
211
- def create!(data, opts = {})
212
- new(data).tap do |model|
213
- model.save!
214
- end
214
+ def create!(data, _opts = {})
215
+ new(data).tap(&:save!)
215
216
  end
216
217
 
217
218
  # @api public
@@ -234,7 +235,7 @@ class Acfs::Resource
234
235
  # will be overridden with provided data hash.
235
236
  # @see #create!
236
237
  #
237
- def create(data, opts = {})
238
+ def create(data, _opts = {})
238
239
  model = new data
239
240
  model.save
240
241
  model
@@ -249,9 +250,8 @@ class Acfs::Resource
249
250
  end
250
251
 
251
252
  def check_loaded!(opts = {})
252
- unless loaded? || opts[:force]
253
- raise ::Acfs::ResourceNotLoaded.new resource: self
254
- end
253
+ return if loaded? || opts[:force]
254
+ raise ::Acfs::ResourceNotLoaded.new resource: self
255
255
  end
256
256
  end
257
257
  end
@@ -1,5 +1,4 @@
1
1
  class Acfs::Resource
2
-
3
2
  # Methods providing the query interface for finding resouces.
4
3
  #
5
4
  # @example
@@ -17,7 +16,6 @@ class Acfs::Resource
17
16
 
18
17
  #
19
18
  module ClassMethods
20
-
21
19
  # @api public
22
20
  #
23
21
  # @overload find(id, opts = {})
@@ -139,7 +137,7 @@ class Acfs::Resource
139
137
  def find_by!(params, &block)
140
138
  find_by params do |m|
141
139
  if m.nil?
142
- raise Acfs::ResourceNotFound.new message: "Recieved erronious " \
140
+ raise Acfs::ResourceNotFound.new message: 'Received erroneous ' \
143
141
  "response: no `#{name}` with params #{params} found"
144
142
  end
145
143
  block.call m unless block.nil?
@@ -225,9 +223,9 @@ class Acfs::Resource
225
223
  collection.__callbacks__ << block unless block.nil?
226
224
 
227
225
  counter = 0
228
- ids.each do |id|
226
+ ids.each_with_index do |id, index|
229
227
  find_single id, opts do |resource|
230
- collection << resource
228
+ collection[index] = resource
231
229
  if (counter += 1) == ids.size
232
230
  collection.loaded!
233
231
  collection.__invoke__
@@ -1,5 +1,4 @@
1
1
  class Acfs::Resource
2
-
3
2
  # Included by Acfs::Model. Allows to configure the service
4
3
  # a resource belongs to.
5
4
  #
@@ -8,7 +7,6 @@ class Acfs::Resource
8
7
 
9
8
  #
10
9
  module ClassMethods
11
-
12
10
  # @api public
13
11
  #
14
12
  # @overload service()
@@ -1,8 +1,6 @@
1
1
  class Acfs::Resource
2
-
3
2
  #
4
3
  module Validation
5
-
6
4
  def valid?(*args)
7
5
  super
8
6
  remote_errors.each {|f, e| errors.add f, e }
@@ -3,7 +3,6 @@ require 'acfs/response/status'
3
3
  require 'active_support/core_ext/module/delegation'
4
4
 
5
5
  module Acfs
6
-
7
6
  # This represents a response. In addition to an standard HTTP
8
7
  # it has a field `data` for storing the encoded body.
9
8
  #
@@ -14,7 +13,7 @@ module Acfs
14
13
  include Response::Formats
15
14
  include Response::Status
16
15
 
17
- #delegate :status, :status_message, :success?, :modified?, :timed_out?,
16
+ # delegate :status, :status_message, :success?, :modified?, :timed_out?,
18
17
  # :response_body, :response_headers, :response_code, :headers,
19
18
  # to: :response
20
19
 
@@ -2,10 +2,8 @@ require 'action_dispatch'
2
2
 
3
3
  module Acfs
4
4
  class Response
5
-
6
5
  # Quick accessors for format handling.
7
6
  module Formats
8
-
9
7
  def content_type
10
8
  @content_type ||= read_content_type
11
9
  end
@@ -15,6 +13,7 @@ module Acfs
15
13
  end
16
14
 
17
15
  private
16
+
18
17
  def read_content_type
19
18
  return 'text/plain' unless headers && headers['Content-Type']
20
19
 
@@ -1,19 +1,17 @@
1
1
  module Acfs
2
2
  class Response
3
-
4
3
  # Method to fetch information about response status.
5
4
  #
6
5
  module Status
7
-
8
6
  # Return response status code. Will return zero if
9
7
  # request was not executed or failed on client side.
10
8
  #
11
9
  def status_code
12
10
  return @status.to_i if defined? :@status
13
- #return response.response_code unless response.nil?
14
- #0
11
+ # return response.response_code unless response.nil?
12
+ # 0
15
13
  end
16
- alias :code :status_code
14
+ alias_method :code, :status_code
17
15
 
18
16
  # Return true if response was successful indicated by
19
17
  # response status code.
@@ -1,7 +1,6 @@
1
1
  require 'acfs/service/middleware'
2
2
 
3
3
  module Acfs
4
-
5
4
  # @api private
6
5
  #
7
6
  class Runner
@@ -17,6 +16,7 @@ module Acfs
17
16
  # and parallel operations will be queued.
18
17
  #
19
18
  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,15 +55,13 @@ module Acfs
55
55
  # Start processing queued operations.
56
56
  #
57
57
  def start
58
- enqueue_operations
58
+ return if running?
59
59
 
60
- @running = true
61
- adapter.start
60
+ enqueue_operations
61
+ start_all
62
62
  rescue
63
63
  queue.clear
64
64
  raise
65
- ensure
66
- @running = false
67
65
  end
68
66
 
69
67
  def clear
@@ -73,15 +71,27 @@ module Acfs
73
71
  end
74
72
 
75
73
  private
74
+
75
+ def start_all
76
+ @running = true
77
+ adapter.start
78
+ ensure
79
+ @running = false
80
+ end
81
+
76
82
  def enqueue_operations
77
83
  while (op = queue.shift)
78
- op_request(op) { |req| adapter.queue req }
84
+ op_request(op) {|req| adapter.queue req }
79
85
  end
80
86
  end
81
87
 
82
88
  def op_request(op)
83
- return if Acfs::Stub.enabled? and Acfs::Stub.stubbed(op)
84
- yield prepare op.service.prepare op.request
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
85
95
  end
86
96
  end
87
97
  end