acfs 0.42.0 → 0.43.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +8 -9
- data/acfs.gemspec +3 -3
- data/lib/acfs.rb +0 -2
- data/lib/acfs/adapter/base.rb +0 -2
- data/lib/acfs/adapter/typhoeus.rb +6 -9
- data/lib/acfs/collection.rb +3 -3
- data/lib/acfs/collections/paginatable.rb +16 -16
- data/lib/acfs/configuration.rb +3 -5
- data/lib/acfs/errors.rb +8 -7
- data/lib/acfs/global.rb +1 -1
- data/lib/acfs/location.rb +11 -11
- data/lib/acfs/middleware/base.rb +1 -2
- data/lib/acfs/middleware/json.rb +0 -1
- data/lib/acfs/middleware/logger.rb +0 -2
- data/lib/acfs/middleware/print.rb +0 -2
- data/lib/acfs/middleware/serializer.rb +3 -6
- data/lib/acfs/operation.rb +3 -4
- data/lib/acfs/request.rb +2 -3
- data/lib/acfs/request/callbacks.rb +2 -3
- data/lib/acfs/resource.rb +34 -5
- data/lib/acfs/{model → resource}/attributes.rb +70 -46
- data/lib/acfs/{model → resource}/attributes/base.rb +10 -6
- data/lib/acfs/resource/attributes/boolean.rb +33 -0
- data/lib/acfs/resource/attributes/date_time.rb +32 -0
- data/lib/acfs/{model → resource}/attributes/dict.rb +1 -3
- data/lib/acfs/{model → resource}/attributes/float.rb +3 -6
- data/lib/acfs/{model → resource}/attributes/integer.rb +3 -6
- data/lib/acfs/{model → resource}/attributes/list.rb +2 -5
- data/lib/acfs/{model → resource}/attributes/string.rb +4 -6
- data/lib/acfs/{model → resource}/attributes/uuid.rb +18 -8
- data/lib/acfs/resource/dirty.rb +47 -0
- data/lib/acfs/{model → resource}/initialization.rb +8 -10
- data/lib/acfs/{model → resource}/loadable.rb +3 -4
- data/lib/acfs/{model → resource}/locatable.rb +22 -23
- data/lib/acfs/{model → resource}/operational.rb +2 -3
- data/lib/acfs/resource/persistence.rb +257 -0
- data/lib/acfs/{model → resource}/query_methods.rb +81 -66
- data/lib/acfs/{model → resource}/service.rb +10 -9
- data/lib/acfs/resource/validation.rb +28 -0
- 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 +4 -5
- data/lib/acfs/service.rb +4 -6
- data/lib/acfs/service/middleware.rb +1 -3
- data/lib/acfs/singleton_resource.rb +11 -24
- data/lib/acfs/stub.rb +30 -22
- data/lib/acfs/util.rb +1 -1
- data/lib/acfs/version.rb +4 -2
- data/spec/acfs/adapter/typhoeus_spec.rb +4 -4
- data/spec/acfs/collection_spec.rb +33 -33
- data/spec/acfs/configuration_spec.rb +0 -1
- data/spec/acfs/global_spec.rb +3 -3
- data/spec/acfs/middleware/json_spec.rb +2 -2
- data/spec/acfs/middleware/msgpack_spec.rb +4 -4
- data/spec/acfs/request/callbacks_spec.rb +8 -8
- data/spec/acfs/request_spec.rb +5 -5
- data/spec/acfs/{model → resource}/attributes/boolean_spec.rb +2 -2
- data/spec/acfs/{model → resource}/attributes/date_time_spec.rb +7 -7
- data/spec/acfs/{model → resource}/attributes/dict_spec.rb +6 -6
- data/spec/acfs/{model → resource}/attributes/float_spec.rb +3 -3
- data/spec/acfs/{model → resource}/attributes/list_spec.rb +5 -5
- data/spec/acfs/{model → resource}/attributes/uuid_spec.rb +6 -6
- data/spec/acfs/{model → resource}/attributes_spec.rb +31 -17
- data/spec/acfs/{model → resource}/dirty_spec.rb +7 -5
- data/spec/acfs/{model → resource}/initialization_spec.rb +7 -7
- data/spec/acfs/{model → resource}/loadable_spec.rb +4 -3
- data/spec/acfs/{model → resource}/locatable_spec.rb +24 -14
- data/spec/acfs/{model → resource}/persistance_spec.rb +34 -34
- data/spec/acfs/{model → resource}/query_methods_spec.rb +171 -130
- data/spec/acfs/{model → resource}/validation_spec.rb +5 -6
- data/spec/acfs/response/formats_spec.rb +1 -1
- data/spec/acfs/response/status_spec.rb +1 -1
- data/spec/acfs/runner_spec.rb +2 -3
- data/spec/acfs/service/middleware_spec.rb +1 -1
- data/spec/acfs/service_spec.rb +3 -5
- data/spec/acfs/singleton_resource_spec.rb +3 -3
- data/spec/acfs/stub_spec.rb +52 -24
- data/spec/acfs_spec.rb +22 -19
- data/spec/spec_helper.rb +1 -1
- data/spec/support/hash.rb +9 -0
- data/spec/support/service.rb +4 -7
- data/spec/support/shared/find_callbacks.rb +7 -7
- metadata +52 -52
- data/lib/acfs/model.rb +0 -43
- data/lib/acfs/model/attributes/boolean.rb +0 -38
- data/lib/acfs/model/attributes/date_time.rb +0 -30
- data/lib/acfs/model/dirty.rb +0 -49
- data/lib/acfs/model/persistence.rb +0 -243
- data/lib/acfs/model/relations.rb +0 -10
- data/lib/acfs/model/validation.rb +0 -30
@@ -0,0 +1,33 @@
|
|
1
|
+
module Acfs::Resource::Attributes
|
2
|
+
# @api public
|
3
|
+
#
|
4
|
+
# Boolean attribute type. Use it in your model as an attribute type:
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# class User < Acfs::Resource
|
8
|
+
# attribute :name, :boolean
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# Given objects will be converted to string. The following strings
|
12
|
+
# are considered true, everything else false:
|
13
|
+
#
|
14
|
+
# true, on, yes
|
15
|
+
#
|
16
|
+
class Boolean < Base
|
17
|
+
TRUE_VALUES = %w(true on yes 1)
|
18
|
+
|
19
|
+
# @api public
|
20
|
+
#
|
21
|
+
# Cast given object to boolean.
|
22
|
+
#
|
23
|
+
# @param [Object] obj Object to cast.
|
24
|
+
# @return [TrueClass, FalseClass] Casted boolean.
|
25
|
+
#
|
26
|
+
def cast_type(obj)
|
27
|
+
return true if obj.is_a? TrueClass
|
28
|
+
return false if obj.is_a? FalseClass
|
29
|
+
|
30
|
+
TRUE_VALUES.include? obj.to_s
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Acfs::Resource::Attributes
|
2
|
+
# @api public
|
3
|
+
#
|
4
|
+
# DateTime attribute type. Use it in your model as
|
5
|
+
# an attribute type:
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# class User < Acfs::Resource
|
9
|
+
# attribute :name, :date_time
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
class DateTime < Base
|
13
|
+
# @api public
|
14
|
+
#
|
15
|
+
# Cast given object to DateTime.
|
16
|
+
#
|
17
|
+
# @param [Object] obj Object to cast.
|
18
|
+
# @return [DateTime] Casted object as DateTime.
|
19
|
+
#
|
20
|
+
def cast_type(obj)
|
21
|
+
if nil_allowed? && obj.blank?
|
22
|
+
nil
|
23
|
+
elsif obj.is_a? ::DateTime
|
24
|
+
obj
|
25
|
+
elsif obj.is_a?(Time) || obj.is_a?(Date)
|
26
|
+
::DateTime.iso8601 obj.iso8601
|
27
|
+
else
|
28
|
+
::DateTime.iso8601 obj
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -1,5 +1,4 @@
|
|
1
|
-
module Acfs::
|
2
|
-
|
1
|
+
module Acfs::Resource::Attributes
|
3
2
|
# @api public
|
4
3
|
#
|
5
4
|
# Dict attribute type. Use it in your model as an attribute type:
|
@@ -11,7 +10,6 @@ module Acfs::Model::Attributes
|
|
11
10
|
# end
|
12
11
|
#
|
13
12
|
class Dict < Base
|
14
|
-
|
15
13
|
# @api public
|
16
14
|
#
|
17
15
|
# Cast given object to a dict/hash.
|
@@ -1,17 +1,14 @@
|
|
1
|
-
module Acfs::
|
2
|
-
|
1
|
+
module Acfs::Resource::Attributes
|
3
2
|
# @api public
|
4
3
|
#
|
5
4
|
# Float attribute type. Use it in your model as an attribute type:
|
6
5
|
#
|
7
6
|
# @example
|
8
|
-
# class User
|
9
|
-
# include Acfs::Model
|
7
|
+
# class User < Acfs::Resource
|
10
8
|
# attribute :name, :float
|
11
9
|
# end
|
12
10
|
#
|
13
11
|
class Float < Base
|
14
|
-
|
15
12
|
# @api public
|
16
13
|
#
|
17
14
|
# Cast given object to float.
|
@@ -20,7 +17,7 @@ module Acfs::Model::Attributes
|
|
20
17
|
# @return [Float] Casted object as float.
|
21
18
|
#
|
22
19
|
def cast_type(obj)
|
23
|
-
obj
|
20
|
+
Float obj
|
24
21
|
end
|
25
22
|
end
|
26
23
|
end
|
@@ -1,17 +1,14 @@
|
|
1
|
-
module Acfs::
|
2
|
-
|
1
|
+
module Acfs::Resource::Attributes
|
3
2
|
# @api public
|
4
3
|
#
|
5
4
|
# Integer attribute type. Use it in your model as an attribute type:
|
6
5
|
#
|
7
6
|
# @example
|
8
|
-
# class User
|
9
|
-
# include Acfs::Model
|
7
|
+
# class User < Acfs::Resource
|
10
8
|
# attribute :name, :integer
|
11
9
|
# end
|
12
10
|
#
|
13
11
|
class Integer < Base
|
14
|
-
|
15
12
|
# @api public
|
16
13
|
#
|
17
14
|
# Cast given object to integer.
|
@@ -20,7 +17,7 @@ module Acfs::Model::Attributes
|
|
20
17
|
# @return [Fixnum] Casted object as fixnum.
|
21
18
|
#
|
22
19
|
def cast_type(obj)
|
23
|
-
obj
|
20
|
+
Integer obj
|
24
21
|
end
|
25
22
|
end
|
26
23
|
end
|
@@ -1,17 +1,14 @@
|
|
1
|
-
module Acfs::
|
2
|
-
|
1
|
+
module Acfs::Resource::Attributes
|
3
2
|
# @api public
|
4
3
|
#
|
5
4
|
# List attribute type. Use it in your model as an attribute type:
|
6
5
|
#
|
7
6
|
# @example
|
8
|
-
# class User
|
9
|
-
# include Acfs::Model
|
7
|
+
# class User < Acfs::Resource
|
10
8
|
# attribute :name, :list
|
11
9
|
# end
|
12
10
|
#
|
13
11
|
class List < Base
|
14
|
-
|
15
12
|
# @api public
|
16
13
|
#
|
17
14
|
# Cast given object to a list.
|
@@ -1,17 +1,15 @@
|
|
1
|
-
module Acfs::
|
2
|
-
|
1
|
+
module Acfs::Resource::Attributes
|
3
2
|
# @api public
|
4
3
|
#
|
5
|
-
# String attribute type. Use it in your model as
|
4
|
+
# String attribute type. Use it in your model as
|
5
|
+
# an attribute type:
|
6
6
|
#
|
7
7
|
# @example
|
8
|
-
# class User
|
9
|
-
# include Acfs::Model
|
8
|
+
# class User < Acfs::Resource
|
10
9
|
# attribute :name, :string
|
11
10
|
# end
|
12
11
|
#
|
13
12
|
class String < Base
|
14
|
-
|
15
13
|
# @api public
|
16
14
|
#
|
17
15
|
# Cast given object to string.
|
@@ -1,16 +1,16 @@
|
|
1
|
-
module Acfs::
|
2
|
-
|
1
|
+
module Acfs::Resource::Attributes
|
3
2
|
# @api public
|
4
3
|
#
|
5
4
|
# UUID attribute type. Use it in your model as an attribute type:
|
6
5
|
#
|
7
6
|
# @example
|
8
|
-
# class User
|
9
|
-
# include Acfs::Model
|
7
|
+
# class User < Acfs::Resource
|
10
8
|
# attribute :id, :uuid
|
11
9
|
# end
|
12
10
|
#
|
13
11
|
class UUID < Base
|
12
|
+
#
|
13
|
+
REGEXP = /[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}/i
|
14
14
|
|
15
15
|
# @api public
|
16
16
|
#
|
@@ -32,10 +32,20 @@ module Acfs::Model::Attributes
|
|
32
32
|
# @return [String] Casted object as UUID.
|
33
33
|
#
|
34
34
|
def cast_type(obj)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
35
|
+
cast_string obj.to_s
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def cast_string(str)
|
41
|
+
if nil_allowed? && str.blank?
|
42
|
+
return nil
|
43
|
+
elsif str =~ REGEXP
|
44
|
+
str
|
45
|
+
else
|
46
|
+
raise ArgumentError.new "given String `#{str}` " \
|
47
|
+
'does not look like a UUID'
|
48
|
+
end
|
39
49
|
end
|
40
50
|
end
|
41
51
|
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class Acfs::Resource
|
2
|
+
#
|
3
|
+
# Thin wrapper around ActiveModel::Dirty
|
4
|
+
#
|
5
|
+
module Dirty
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
include ActiveModel::Dirty
|
8
|
+
|
9
|
+
# @api private
|
10
|
+
#
|
11
|
+
# Resets all changes. Does not touch previous changes.
|
12
|
+
#
|
13
|
+
def reset_changes
|
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
|
25
|
+
end
|
26
|
+
|
27
|
+
# @api private
|
28
|
+
#
|
29
|
+
def save!(*)
|
30
|
+
super.tap {|_| swap_changes }
|
31
|
+
end
|
32
|
+
|
33
|
+
# @api private
|
34
|
+
#
|
35
|
+
def loaded!
|
36
|
+
reset_changes
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
40
|
+
# @api private
|
41
|
+
#
|
42
|
+
def write_raw_attribute(name, value, opts = {})
|
43
|
+
attribute_will_change! name if opts[:change].nil? || opts[:change]
|
44
|
+
super
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -1,18 +1,17 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
class Acfs::Resource
|
2
|
+
#
|
3
3
|
# Initialization drop-in for pre-4.0 ActiveModel.
|
4
4
|
#
|
5
5
|
module Initialization
|
6
|
-
|
6
|
+
#
|
7
7
|
# @api public
|
8
8
|
#
|
9
|
-
# Initializes a new model with the given `params`.
|
9
|
+
# Initializes a new model with the given `params`. fff
|
10
10
|
#
|
11
11
|
# @example
|
12
|
-
# class User
|
13
|
-
# include Acfs::Model
|
12
|
+
# class User < Acfs::Resource
|
14
13
|
# attribute :name
|
15
|
-
# attribute :email, default: ->
|
14
|
+
# attribute :email, default: ->{ "#{name}@dom.tld" }
|
16
15
|
# attribute :age, :integer, default: 18
|
17
16
|
# end
|
18
17
|
#
|
@@ -21,11 +20,10 @@ module Acfs::Model
|
|
21
20
|
# user.email # => "bob@dom.tld"
|
22
21
|
# user.age # => 18
|
23
22
|
#
|
24
|
-
# @param [
|
23
|
+
# @param params [Hash{Symbol => Object}] Attributes to set on resource.
|
25
24
|
#
|
26
25
|
def initialize(params = {})
|
27
|
-
|
26
|
+
write_attributes params if params
|
28
27
|
end
|
29
|
-
|
30
28
|
end
|
31
29
|
end
|
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
class Acfs::Resource
|
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}.
|
@@ -17,10 +16,10 @@ module Acfs::Model
|
|
17
16
|
#
|
18
17
|
# Check if model is loaded or if request is still queued.
|
19
18
|
#
|
20
|
-
# @return [
|
19
|
+
# @return [Boolean] True if resource is loaded, false otherwise.
|
21
20
|
#
|
22
21
|
def loaded?
|
23
|
-
|
22
|
+
@loaded.nil? ? false : @loaded
|
24
23
|
end
|
25
24
|
|
26
25
|
# @api private
|
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
class Acfs::Resource
|
3
2
|
# Provide methods for generation URLs for resources.
|
4
3
|
#
|
5
4
|
# @example
|
@@ -12,36 +11,36 @@ module Acfs::Model
|
|
12
11
|
module Locatable
|
13
12
|
extend ActiveSupport::Concern
|
14
13
|
|
14
|
+
#
|
15
15
|
module ClassMethods
|
16
|
-
|
17
16
|
# @overload url(suffix)
|
18
17
|
# @deprecated
|
19
|
-
# Return URL for this class of resource. Given suffix
|
18
|
+
# Return URL for this class of resource. Given suffix
|
19
|
+
# will be appended.
|
20
20
|
#
|
21
21
|
# @example
|
22
22
|
# User.url # => "http://users.srv.org/users"
|
23
23
|
# User.url(5) # => "http://users.srv.org/users/5"
|
24
24
|
#
|
25
|
-
# @param [
|
26
|
-
# @return [
|
25
|
+
# @param suffix [String] Suffix to append to URL.
|
26
|
+
# @return [String] Generated URL.
|
27
27
|
#
|
28
28
|
# @overload url(opts = {})
|
29
|
-
# Return URL for this class of resources. Given options
|
30
|
-
# URL path arguments and to
|
29
|
+
# Return URL for this class of resources. Given options
|
30
|
+
# will be used to replace URL path arguments and to
|
31
|
+
# determine the operation action.
|
31
32
|
#
|
32
33
|
# @example
|
33
34
|
# User.url(id: 5, action: :read) # => "http://users.srv.org/users/5"
|
34
35
|
# User.url(action: :list) # => "http://users.srv.org/users"
|
35
36
|
#
|
36
37
|
# @param opts [Hash] Options.
|
37
|
-
# @option opts [Symbol] :action Operation action,
|
38
|
-
# `:update` or`:delete`.
|
39
|
-
# @return [
|
38
|
+
# @option opts [Symbol] :action Operation action,
|
39
|
+
# usually `:list`, `:create`, `:read`, `:update` or`:delete`.
|
40
|
+
# @return [String] Generated URL.
|
40
41
|
#
|
41
42
|
def url(suffix = nil, opts = {})
|
42
|
-
|
43
|
-
opts, suffix = suffix, nil
|
44
|
-
end
|
43
|
+
opts, suffix = suffix, nil if suffix.is_a? Hash
|
45
44
|
|
46
45
|
opts[:action] = :list if suffix
|
47
46
|
|
@@ -50,8 +49,8 @@ module Acfs::Model
|
|
50
49
|
url
|
51
50
|
end
|
52
51
|
|
53
|
-
# Return a location object able to build the URL for this
|
54
|
-
# given action.
|
52
|
+
# Return a location object able to build the URL for this
|
53
|
+
# resource and given action.
|
55
54
|
#
|
56
55
|
# @example
|
57
56
|
# class Identity < ::Acfs::Resource
|
@@ -73,8 +72,8 @@ module Acfs::Model
|
|
73
72
|
# => 'http://service/users/42/identities'
|
74
73
|
#
|
75
74
|
# @param opts [Hash] Options.
|
76
|
-
# @option opts [Symbol] :action Operation action,
|
77
|
-
# `:update` or`:delete`.
|
75
|
+
# @option opts [Symbol] :action Operation action,
|
76
|
+
# usually `:list`, `:create`, `:read`, `:update` or`:delete`.
|
78
77
|
#
|
79
78
|
# @return [Location] Location object.
|
80
79
|
#
|
@@ -89,8 +88,6 @@ module Acfs::Model
|
|
89
88
|
return path
|
90
89
|
when :read, :update, :delete
|
91
90
|
return "#{path}/:id"
|
92
|
-
else
|
93
|
-
nil
|
94
91
|
end
|
95
92
|
end
|
96
93
|
end
|
@@ -109,9 +106,11 @@ module Acfs::Model
|
|
109
106
|
# @see ClassMethods#url
|
110
107
|
#
|
111
108
|
def url(opts = {})
|
112
|
-
return nil if need_primary_key? && !
|
109
|
+
return nil if need_primary_key? && !primary_key?
|
113
110
|
|
114
|
-
self.class.service
|
111
|
+
self.class.service
|
112
|
+
.location(self.class, opts.reverse_merge(action: :read))
|
113
|
+
.build(attributes).str
|
115
114
|
end
|
116
115
|
|
117
116
|
# @api private
|
@@ -122,7 +121,7 @@ module Acfs::Model
|
|
122
121
|
|
123
122
|
# @api private
|
124
123
|
# Return true if resource has a primary key (id) set.
|
125
|
-
def
|
124
|
+
def primary_key?
|
126
125
|
respond_to?(:id) && !id.nil?
|
127
126
|
end
|
128
127
|
end
|
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
class Acfs::Resource
|
3
2
|
# @api private
|
4
3
|
#
|
5
4
|
# Provide methods for creating and processing CRUD operations and
|
@@ -12,8 +11,8 @@ module Acfs::Model
|
|
12
11
|
extend ActiveSupport::Concern
|
13
12
|
delegate :operation, to: :'self.class'
|
14
13
|
|
14
|
+
#
|
15
15
|
module ClassMethods
|
16
|
-
|
17
16
|
# Invoke CRUD operation.
|
18
17
|
def operation(action, opts = {}, &block)
|
19
18
|
Acfs.runner.process ::Acfs::Operation.new self, action, opts, &block
|