acfs 1.0.0.dev.1.b305 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/CHANGELOG.md +64 -0
- data/README.md +2 -2
- data/acfs.gemspec +4 -4
- data/lib/acfs.rb +7 -5
- data/lib/acfs/adapter/base.rb +0 -2
- data/lib/acfs/adapter/typhoeus.rb +17 -13
- data/lib/acfs/collections/paginatable.rb +10 -10
- data/lib/acfs/configuration.rb +4 -5
- data/lib/acfs/errors.rb +10 -9
- data/lib/acfs/global.rb +16 -7
- data/lib/acfs/location.rb +11 -11
- data/lib/acfs/middleware/base.rb +1 -2
- data/lib/acfs/middleware/json.rb +27 -0
- data/lib/acfs/middleware/logger.rb +0 -2
- data/lib/acfs/middleware/msgpack.rb +30 -0
- data/lib/acfs/middleware/print.rb +0 -2
- data/lib/acfs/middleware/serializer.rb +39 -0
- data/lib/acfs/operation.rb +5 -5
- data/lib/acfs/request.rb +4 -4
- data/lib/acfs/request/callbacks.rb +2 -3
- data/lib/acfs/resource.rb +2 -2
- data/lib/acfs/resource/attributes.rb +10 -37
- data/lib/acfs/resource/attributes/base.rb +10 -19
- data/lib/acfs/resource/attributes/boolean.rb +10 -8
- data/lib/acfs/resource/attributes/date_time.rb +6 -9
- data/lib/acfs/resource/attributes/dict.rb +37 -0
- data/lib/acfs/resource/attributes/float.rb +11 -5
- data/lib/acfs/resource/attributes/integer.rb +7 -5
- data/lib/acfs/resource/attributes/list.rb +13 -6
- data/lib/acfs/resource/attributes/string.rb +3 -5
- data/lib/acfs/resource/attributes/uuid.rb +8 -17
- data/lib/acfs/resource/loadable.rb +0 -1
- data/lib/acfs/resource/locatable.rb +0 -4
- data/lib/acfs/resource/operational.rb +0 -2
- data/lib/acfs/resource/persistence.rb +17 -17
- data/lib/acfs/resource/query_methods.rb +3 -5
- data/lib/acfs/resource/service.rb +0 -2
- data/lib/acfs/resource/validation.rb +0 -2
- data/lib/acfs/response.rb +1 -2
- data/lib/acfs/response/formats.rb +1 -2
- data/lib/acfs/response/status.rb +3 -5
- data/lib/acfs/runner.rb +21 -11
- data/lib/acfs/service.rb +4 -6
- data/lib/acfs/service/middleware.rb +20 -30
- data/lib/acfs/service/middleware/stack.rb +63 -0
- data/lib/acfs/singleton_resource.rb +0 -2
- data/lib/acfs/stub.rb +30 -21
- data/lib/acfs/util.rb +1 -1
- data/lib/acfs/version.rb +4 -2
- data/spec/acfs/adapter/typhoeus_spec.rb +12 -4
- data/spec/acfs/collection_spec.rb +45 -33
- data/spec/acfs/configuration_spec.rb +9 -1
- data/spec/acfs/global_spec.rb +21 -3
- data/spec/acfs/middleware/json_spec.rb +63 -0
- data/spec/acfs/middleware/msgpack_spec.rb +60 -0
- data/spec/acfs/operation_spec.rb +10 -0
- data/spec/acfs/request/callbacks_spec.rb +8 -8
- data/spec/acfs/request_spec.rb +5 -5
- data/spec/acfs/resource/attributes/boolean_spec.rb +40 -9
- data/spec/acfs/resource/attributes/date_time_spec.rb +29 -35
- data/spec/acfs/resource/attributes/dict_spec.rb +75 -0
- data/spec/acfs/resource/attributes/float_spec.rb +48 -9
- data/spec/acfs/resource/attributes/integer_spec.rb +34 -0
- data/spec/acfs/resource/attributes/list_spec.rb +43 -19
- data/spec/acfs/resource/attributes/uuid_spec.rb +31 -54
- data/spec/acfs/resource/attributes_spec.rb +17 -31
- data/spec/acfs/resource/locatable_spec.rb +2 -2
- data/spec/acfs/resource/persistance_spec.rb +65 -34
- data/spec/acfs/resource/query_methods_spec.rb +87 -87
- data/spec/acfs/resource/validation_spec.rb +4 -5
- data/spec/acfs/response/formats_spec.rb +1 -1
- data/spec/acfs/response/status_spec.rb +1 -1
- data/spec/acfs/runner_spec.rb +28 -3
- data/spec/acfs/service/middleware_spec.rb +4 -20
- data/spec/acfs/service_spec.rb +3 -5
- data/spec/acfs/singleton_resource_spec.rb +1 -2
- data/spec/acfs/stub_spec.rb +137 -22
- data/spec/acfs_spec.rb +22 -19
- data/spec/spec_helper.rb +2 -1
- data/spec/support/service.rb +10 -6
- data/spec/support/shared/find_callbacks.rb +7 -7
- metadata +37 -30
- data/lib/acfs/middleware/json_decoder.rb +0 -16
- data/lib/acfs/middleware/json_encoder.rb +0 -20
- data/lib/acfs/middleware/msgpack_decoder.rb +0 -26
- data/lib/acfs/middleware/msgpack_encoder.rb +0 -19
- data/spec/acfs/middleware/json_decoder_spec.rb +0 -45
- 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]
|
16
|
+
# @param [Object] value Object to cast.
|
19
17
|
# @return [Float] Casted object as float.
|
20
18
|
#
|
21
|
-
def
|
22
|
-
|
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]
|
16
|
+
# @param [Object] value Object to cast.
|
19
17
|
# @return [Fixnum] Casted object as fixnum.
|
20
18
|
#
|
21
|
-
def
|
22
|
-
|
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]
|
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
|
23
|
-
return
|
24
|
-
|
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]
|
17
|
+
# @param [Object] value Object to cast.
|
20
18
|
# @return [String] Casted string.
|
21
19
|
#
|
22
|
-
def
|
23
|
-
|
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
|
-
|
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]
|
31
|
+
# @param [Object] value Object to cast.
|
34
32
|
# @return [String] Casted object as UUID.
|
35
33
|
#
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
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
|
# 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
|
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? # =>
|
23
|
+
# user2.persisted? # => true
|
25
24
|
# user2.save
|
26
25
|
# user2.persisted? # => true
|
27
26
|
#
|
28
|
-
# @return [Boolean] True if resource has
|
29
|
-
# is not newly created, false otherwise.
|
27
|
+
# @return [Boolean] True if resource has been saved
|
30
28
|
#
|
31
29
|
def persisted?
|
32
|
-
!new?
|
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
|
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,
|
212
|
-
new(data).tap
|
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,
|
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
|
-
|
253
|
-
|
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:
|
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.
|
226
|
+
ids.each_with_index do |id, index|
|
229
227
|
find_single id, opts do |resource|
|
230
|
-
collection
|
228
|
+
collection[index] = resource
|
231
229
|
if (counter += 1) == ids.size
|
232
230
|
collection.loaded!
|
233
231
|
collection.__invoke__
|
data/lib/acfs/response.rb
CHANGED
@@ -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
|
|
data/lib/acfs/response/status.rb
CHANGED
@@ -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
|
-
|
14
|
+
alias_method :code, :status_code
|
17
15
|
|
18
16
|
# Return true if response was successful indicated by
|
19
17
|
# response status code.
|
data/lib/acfs/runner.rb
CHANGED
@@ -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) {
|
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) {
|
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
|
-
|
58
|
+
return if running?
|
59
59
|
|
60
|
-
|
61
|
-
|
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) {
|
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?
|
84
|
-
|
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
|