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
@@ -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