acfs 0.50.0 → 1.0.0.dev.1.b297

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 (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
@@ -1,4 +1,5 @@
1
1
  module Acfs::Resource::Attributes
2
+
2
3
  # @api public
3
4
  #
4
5
  # DateTime attribute type. Use it in your model as
@@ -15,16 +16,18 @@ module Acfs::Resource::Attributes
15
16
  #
16
17
  # Cast given object to DateTime.
17
18
  #
18
- # @param [Object] value Object to cast.
19
+ # @param [Object] obj Object to cast.
19
20
  # @return [DateTime] Casted object as DateTime.
20
21
  #
21
- def cast_value(value)
22
- if value.blank?
22
+ def cast_type(obj)
23
+ if nil_allowed? && obj.blank?
23
24
  nil
24
- elsif value.acts_like?(:time) || value.acts_like?(:date)
25
- value.to_datetime
25
+ elsif obj.is_a? ::DateTime
26
+ obj
27
+ elsif obj.is_a?(Time) || obj.is_a?(Date)
28
+ ::DateTime.iso8601 obj.iso8601
26
29
  else
27
- ::DateTime.iso8601 value
30
+ ::DateTime.iso8601 obj
28
31
  end
29
32
  end
30
33
  end
@@ -1,4 +1,5 @@
1
1
  module Acfs::Resource::Attributes
2
+
2
3
  # @api public
3
4
  #
4
5
  # Float attribute type. Use it in your model as an attribute type:
@@ -9,23 +10,16 @@ module Acfs::Resource::Attributes
9
10
  # end
10
11
  #
11
12
  class Float < Base
13
+
12
14
  # @api public
13
15
  #
14
16
  # Cast given object to float.
15
17
  #
16
- # @param [Object] value Object to cast.
18
+ # @param [Object] obj Object to cast.
17
19
  # @return [Float] Casted object as float.
18
20
  #
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
21
+ def cast_type(obj)
22
+ Float obj
29
23
  end
30
24
  end
31
25
  end
@@ -1,4 +1,5 @@
1
1
  module Acfs::Resource::Attributes
2
+
2
3
  # @api public
3
4
  #
4
5
  # Integer attribute type. Use it in your model as an attribute type:
@@ -9,19 +10,16 @@ module Acfs::Resource::Attributes
9
10
  # end
10
11
  #
11
12
  class Integer < Base
13
+
12
14
  # @api public
13
15
  #
14
16
  # Cast given object to integer.
15
17
  #
16
- # @param [Object] value Object to cast.
18
+ # @param [Object] obj Object to cast.
17
19
  # @return [Fixnum] Casted object as fixnum.
18
20
  #
19
- def cast_value(value)
20
- if value.blank?
21
- 0
22
- else
23
- Integer(value)
24
- end
21
+ def cast_type(obj)
22
+ Integer obj
25
23
  end
26
24
  end
27
25
  end
@@ -1,4 +1,5 @@
1
1
  module Acfs::Resource::Attributes
2
+
2
3
  # @api public
3
4
  #
4
5
  # List attribute type. Use it in your model as an attribute type:
@@ -9,26 +10,18 @@ module Acfs::Resource::Attributes
9
10
  # end
10
11
  #
11
12
  class List < Base
13
+
12
14
  # @api public
13
15
  #
14
16
  # Cast given object to a list.
15
17
  #
16
- # @param [Object] value Object to cast.
18
+ # @param [Object] obj Object to cast.
17
19
  # @return [Fixnum] Casted object as list.
18
20
  # @raise [TypeError] If object cannot be casted to a list.
19
21
  #
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
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."
32
25
  end
33
26
  end
34
27
  end
@@ -1,4 +1,5 @@
1
1
  module Acfs::Resource::Attributes
2
+
2
3
  # @api public
3
4
  #
4
5
  # String attribute type. Use it in your model as
@@ -10,15 +11,16 @@ module Acfs::Resource::Attributes
10
11
  # end
11
12
  #
12
13
  class String < Base
14
+
13
15
  # @api public
14
16
  #
15
17
  # Cast given object to string.
16
18
  #
17
- # @param [Object] value Object to cast.
19
+ # @param [Object] obj Object to cast.
18
20
  # @return [String] Casted string.
19
21
  #
20
- def cast_value(value)
21
- value.to_s
22
+ def cast_type(obj)
23
+ obj.to_s
22
24
  end
23
25
  end
24
26
  end
@@ -1,4 +1,5 @@
1
1
  module Acfs::Resource::Attributes
2
+
2
3
  # @api public
3
4
  #
4
5
  # UUID attribute type. Use it in your model as an attribute type:
@@ -9,8 +10,9 @@ module Acfs::Resource::Attributes
9
10
  # end
10
11
  #
11
12
  class UUID < Base
13
+
12
14
  #
13
- UUID_REGEXP = /[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}/i
15
+ REGEXP = /[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}/i
14
16
 
15
17
  # @api public
16
18
  #
@@ -28,16 +30,23 @@ module Acfs::Resource::Attributes
28
30
  # | 4 | 4 |
29
31
  # | 5 | 12 |
30
32
  #
31
- # @param [Object] value Object to cast.
33
+ # @param [Object] obj Object to cast.
32
34
  # @return [String] Casted object as UUID.
33
35
  #
34
- def cast_value(value)
35
- if value.blank?
36
- nil
37
- elsif value.to_s =~ UUID_REGEXP
38
- value
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
39
47
  else
40
- raise TypeError.new "Invalid UUID: `#{value.to_s}'"
48
+ raise ArgumentError.new "given String `#{str}` " \
49
+ "does not look like a UUID"
41
50
  end
42
51
  end
43
52
  end
@@ -8,14 +8,26 @@ class Acfs::Resource
8
8
 
9
9
  # @api private
10
10
  #
11
+ # Resets all changes. Does not touch previous changes.
12
+ #
11
13
  def reset_changes
12
- clear_changes_information
14
+ changed_attributes.clear
15
+ end
16
+
17
+ # @api private
18
+ #
19
+ # Save current changes as previous changes and reset
20
+ # current one.
21
+ #
22
+ def swap_changes
23
+ @previously_changed = changes
24
+ reset_changes
13
25
  end
14
26
 
15
27
  # @api private
16
28
  #
17
29
  def save!(*)
18
- super.tap {|_| changes_applied }
30
+ super.tap {|_| swap_changes }
19
31
  end
20
32
 
21
33
  # @api private
@@ -28,7 +40,7 @@ class Acfs::Resource
28
40
  # @api private
29
41
  #
30
42
  def write_raw_attribute(name, value, opts = {})
31
- attribute_will_change!(name) if opts[:change].nil? || opts[:change]
43
+ attribute_will_change! name if opts[:change].nil? || opts[:change]
32
44
  super
33
45
  end
34
46
  end
@@ -1,4 +1,5 @@
1
1
  class Acfs::Resource
2
+
2
3
  # Provides method to check for loading state of resources.
3
4
  # A resource that is created but not yet fetched will be loaded
4
5
  # after running {Acfs::Global#run Acfs.run}.
@@ -1,4 +1,5 @@
1
1
  class Acfs::Resource
2
+
2
3
  # Provide methods for generation URLs for resources.
3
4
  #
4
5
  # @example
@@ -13,6 +14,7 @@ class Acfs::Resource
13
14
 
14
15
  #
15
16
  module ClassMethods
17
+
16
18
  # @overload url(suffix)
17
19
  # @deprecated
18
20
  # Return URL for this class of resource. Given suffix
@@ -88,6 +90,8 @@ class Acfs::Resource
88
90
  return path
89
91
  when :read, :update, :delete
90
92
  return "#{path}/:id"
93
+ else
94
+ nil
91
95
  end
92
96
  end
93
97
  end
@@ -1,4 +1,5 @@
1
1
  class Acfs::Resource
2
+
2
3
  # @api private
3
4
  #
4
5
  # Provide methods for creating and processing CRUD operations and
@@ -13,6 +14,7 @@ class Acfs::Resource
13
14
 
14
15
  #
15
16
  module ClassMethods
17
+
16
18
  # Invoke CRUD operation.
17
19
  def operation(action, opts = {}, &block)
18
20
  Acfs.runner.process ::Acfs::Operation.new self, action, opts, &block
@@ -8,7 +8,8 @@ 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
11
+ # it is saved after being created or when it was not changed
12
+ # since it was loaded.
12
13
  #
13
14
  # @example Newly created resource:
14
15
  # user = User.new name: "John"
@@ -20,14 +21,15 @@ class Acfs::Resource
20
21
  # user2 = User.find 5
21
22
  # user2.persisted? # => true
22
23
  # user2.name = 'Amy'
23
- # user2.persisted? # => true
24
+ # user2.persisted? # => false
24
25
  # user2.save
25
26
  # user2.persisted? # => true
26
27
  #
27
- # @return [Boolean] True if resource has been saved
28
+ # @return [Boolean] True if resource has no changes and
29
+ # is not newly created, false otherwise.
28
30
  #
29
31
  def persisted?
30
- !new?
32
+ !new? && !changed?
31
33
  end
32
34
 
33
35
  # @api public
@@ -172,7 +174,7 @@ class Acfs::Resource
172
174
  #
173
175
  def delete!(opts = {})
174
176
  opts[:params] ||= {}
175
- opts[:params] = attributes_for_url(:delete).merge opts[:params]
177
+ opts[:params].merge! id: id
176
178
 
177
179
  operation :delete, opts do |data|
178
180
  update_with data
@@ -180,14 +182,9 @@ class Acfs::Resource
180
182
  end
181
183
  end
182
184
 
183
- private
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
-
185
+ #
190
186
  module ClassMethods
187
+
191
188
  # @api public
192
189
  #
193
190
  # Create a new resource sending given data. If resource cannot be
@@ -211,8 +208,10 @@ class Acfs::Resource
211
208
  # will be overridden with provided data hash.
212
209
  # @see #create
213
210
  #
214
- def create!(data, _opts = {})
215
- new(data).tap(&:save!)
211
+ def create!(data, opts = {})
212
+ new(data).tap do |model|
213
+ model.save!
214
+ end
216
215
  end
217
216
 
218
217
  # @api public
@@ -235,7 +234,7 @@ class Acfs::Resource
235
234
  # will be overridden with provided data hash.
236
235
  # @see #create!
237
236
  #
238
- def create(data, _opts = {})
237
+ def create(data, opts = {})
239
238
  model = new data
240
239
  model.save
241
240
  model
@@ -250,8 +249,9 @@ class Acfs::Resource
250
249
  end
251
250
 
252
251
  def check_loaded!(opts = {})
253
- return if loaded? || opts[:force]
254
- raise ::Acfs::ResourceNotLoaded.new resource: self
252
+ unless loaded? || opts[:force]
253
+ raise ::Acfs::ResourceNotLoaded.new resource: self
254
+ end
255
255
  end
256
256
  end
257
257
  end
@@ -1,4 +1,5 @@
1
1
  class Acfs::Resource
2
+
2
3
  # Methods providing the query interface for finding resouces.
3
4
  #
4
5
  # @example
@@ -16,6 +17,7 @@ class Acfs::Resource
16
17
 
17
18
  #
18
19
  module ClassMethods
20
+
19
21
  # @api public
20
22
  #
21
23
  # @overload find(id, opts = {})
@@ -137,7 +139,7 @@ class Acfs::Resource
137
139
  def find_by!(params, &block)
138
140
  find_by params do |m|
139
141
  if m.nil?
140
- raise Acfs::ResourceNotFound.new message: 'Received erroneous ' \
142
+ raise Acfs::ResourceNotFound.new message: "Recieved erronious " \
141
143
  "response: no `#{name}` with params #{params} found"
142
144
  end
143
145
  block.call m unless block.nil?
@@ -193,13 +195,10 @@ class Acfs::Resource
193
195
  #
194
196
  # @yield [item] Callback that will be invoked for each item.
195
197
  # @yieldparam item [self] Resource.
196
- # @yieldparam collection [Acfs::Collection] Collection.
197
198
  #
198
- def each_item(opts = {})
199
+ def each_item(opts = {}, &block)
199
200
  each_page(opts) do |collection|
200
- collection.each do |item|
201
- yield item, collection
202
- end
201
+ collection.each(&block)
203
202
  end
204
203
  end
205
204
 
@@ -226,9 +225,9 @@ class Acfs::Resource
226
225
  collection.__callbacks__ << block unless block.nil?
227
226
 
228
227
  counter = 0
229
- ids.each_with_index do |id, index|
228
+ ids.each do |id|
230
229
  find_single id, opts do |resource|
231
- collection[index] = resource
230
+ collection << resource
232
231
  if (counter += 1) == ids.size
233
232
  collection.loaded!
234
233
  collection.__invoke__
@@ -1,4 +1,5 @@
1
1
  class Acfs::Resource
2
+
2
3
  # Included by Acfs::Model. Allows to configure the service
3
4
  # a resource belongs to.
4
5
  #
@@ -7,6 +8,7 @@ class Acfs::Resource
7
8
 
8
9
  #
9
10
  module ClassMethods
11
+
10
12
  # @api public
11
13
  #
12
14
  # @overload service()
@@ -1,6 +1,8 @@
1
1
  class Acfs::Resource
2
+
2
3
  #
3
4
  module Validation
5
+
4
6
  def valid?(*args)
5
7
  super
6
8
  remote_errors.each {|f, e| errors.add f, e }
@@ -13,10 +15,8 @@ class Acfs::Resource
13
15
 
14
16
  def remote_errors=(errors)
15
17
  (errors || []).each do |field, errs|
16
- errs.each do |err|
17
- self.errors.add field.to_sym, err
18
- remote_errors.add field.to_sym, err
19
- end
18
+ self.errors.set field.to_sym, errs
19
+ remote_errors.set field.to_sym, errs
20
20
  end
21
21
  end
22
22