acfs 0.42.0 → 0.43.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.
- 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
|