u-attributes 2.4.0 → 2.5.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/README.md +2 -2
- data/lib/micro/attributes.rb +18 -8
- data/lib/micro/attributes/diff.rb +4 -4
- data/lib/micro/attributes/features.rb +85 -27
- data/lib/micro/attributes/features/accept.rb +132 -0
- data/lib/micro/attributes/features/accept/strict.rb +26 -0
- data/lib/micro/attributes/features/activemodel_validations.rb +53 -9
- data/lib/micro/attributes/features/initialize.rb +3 -8
- data/lib/micro/attributes/features/keys_as_symbol.rb +3 -3
- data/lib/micro/attributes/macros.rb +62 -15
- data/lib/micro/attributes/version.rb +1 -1
- metadata +4 -3
- data/lib/micro/attributes/with.rb +0 -182
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 01dbce30afd7d116e15ea5985e5012d86f2bd110b017394151086df322e9b7ed
|
4
|
+
data.tar.gz: 4004e27e835cc216807b2fb2781a15911c16f2ba20e509b7c36188a8b6021f95
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ca177ca900f63a07901366612f5ef545512db4e8f9b48bea6482403af6346324784910fa9dca963e681449a1d3b583b173317890b76e8a2e03fd46b58af32006
|
7
|
+
data.tar.gz: 44372485364d637906d1dad476fc58a98cf228c33e252012af320e7e1da36b82db3943eb635ed34dff211908088f6fc8fe3c2de8a1b9a418f62f8e8b3e1596ed
|
data/README.md
CHANGED
@@ -85,7 +85,7 @@ gem 'u-attributes'
|
|
85
85
|
|
86
86
|
| u-attributes | branch | ruby | activemodel |
|
87
87
|
| -------------- | ------- | -------- | ------------- |
|
88
|
-
| 2.
|
88
|
+
| 2.5.0 | main | >= 2.2.0 | >= 3.2, < 6.1 |
|
89
89
|
| 1.2.0 | v1.x | >= 2.2.0 | >= 3.2, < 6.1 |
|
90
90
|
|
91
91
|
> **Note**: The activemodel is an optional dependency, this module [can be enabled](#activemodelvalidation-extension) to validate the attributes.
|
@@ -618,7 +618,7 @@ The method `Micro::Attributes.with()` will raise an exception if no arguments/fe
|
|
618
618
|
|
619
619
|
```ruby
|
620
620
|
class Job
|
621
|
-
include Micro::Attributes.with() # ArgumentError (Invalid feature name! Available options: :activemodel_validations, :diff, :initialize, :keys_as_symbol)
|
621
|
+
include Micro::Attributes.with() # ArgumentError (Invalid feature name! Available options: :accept, :activemodel_validations, :diff, :initialize, :keys_as_symbol)
|
622
622
|
end
|
623
623
|
```
|
624
624
|
|
data/lib/micro/attributes.rb
CHANGED
@@ -16,6 +16,7 @@ module Micro
|
|
16
16
|
base.class_eval do
|
17
17
|
private_class_method :__attributes, :__attribute_reader
|
18
18
|
private_class_method :__attribute_assign, :__attributes_data_to_assign
|
19
|
+
private_class_method :__attributes_required_add, :__attributes_data_to_assign
|
19
20
|
end
|
20
21
|
|
21
22
|
def base.inherited(subclass)
|
@@ -86,29 +87,36 @@ module Micro
|
|
86
87
|
protected
|
87
88
|
|
88
89
|
def attributes=(arg)
|
89
|
-
hash = self.class.
|
90
|
+
hash = self.class.__attributes_keys_transform__(arg)
|
90
91
|
|
91
92
|
__attributes_missing!(hash)
|
92
93
|
|
94
|
+
__call_before_attributes_assign
|
93
95
|
__attributes_assign(hash)
|
96
|
+
__call_after_attributes_assign
|
97
|
+
|
98
|
+
__attributes
|
94
99
|
end
|
95
100
|
|
96
101
|
private
|
97
102
|
|
103
|
+
def __call_before_attributes_assign; end
|
104
|
+
def __call_after_attributes_assign; end
|
105
|
+
|
98
106
|
def extract_attributes_from(other)
|
99
107
|
Utils::ExtractAttribute.from(other, keys: defined_attributes)
|
100
108
|
end
|
101
109
|
|
102
110
|
def __attribute_key(value)
|
103
|
-
self.class.
|
111
|
+
self.class.__attribute_key_transform__(value)
|
104
112
|
end
|
105
113
|
|
106
114
|
def __attributes
|
107
115
|
@__attributes ||= {}
|
108
116
|
end
|
109
117
|
|
110
|
-
FetchValueToAssign = -> (value, default) do
|
111
|
-
if default.is_a?(Proc)
|
118
|
+
FetchValueToAssign = -> (value, default, keep_proc = false) do
|
119
|
+
if default.is_a?(Proc) && !keep_proc
|
112
120
|
default.arity > 0 ? default.call(value) : default.call
|
113
121
|
else
|
114
122
|
value.nil? ? default : value
|
@@ -116,15 +124,17 @@ module Micro
|
|
116
124
|
end
|
117
125
|
|
118
126
|
def __attributes_assign(hash)
|
119
|
-
self.class.__attributes_data__.each do |name,
|
120
|
-
__attribute_assign(name,
|
127
|
+
self.class.__attributes_data__.each do |name, attribute_data|
|
128
|
+
__attribute_assign(name, hash[name], attribute_data) if attribute?(name)
|
121
129
|
end
|
122
130
|
|
123
131
|
__attributes.freeze
|
124
132
|
end
|
125
133
|
|
126
|
-
def __attribute_assign(name,
|
127
|
-
|
134
|
+
def __attribute_assign(name, initialize_value, attribute_data)
|
135
|
+
value_to_assign = FetchValueToAssign.(initialize_value, attribute_data[0])
|
136
|
+
|
137
|
+
__attributes[name] = instance_variable_set("@#{name}", value_to_assign)
|
128
138
|
end
|
129
139
|
|
130
140
|
MISSING_KEYWORD = 'missing keyword'.freeze
|
@@ -35,17 +35,17 @@ module Micro::Attributes
|
|
35
35
|
|
36
36
|
raise ArgumentError, FROM_TO_ERROR
|
37
37
|
elsif from.nil? && to.nil?
|
38
|
-
differences.has_key?(
|
38
|
+
differences.has_key?(key_transform(name))
|
39
39
|
else
|
40
|
-
result = @differences[
|
40
|
+
result = @differences[key_transform(name)]
|
41
41
|
result ? result[@from_key] == from && result[@to_key] == to : false
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
45
|
private
|
46
46
|
|
47
|
-
def
|
48
|
-
@from_class.
|
47
|
+
def key_transform(key)
|
48
|
+
@from_class.__attribute_key_transform__(key)
|
49
49
|
end
|
50
50
|
|
51
51
|
def diff(from_attributes, to_attributes)
|
@@ -1,15 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'micro/attributes/with'
|
4
|
-
|
5
3
|
module Micro
|
6
4
|
module Attributes
|
5
|
+
module With
|
6
|
+
end
|
7
|
+
|
7
8
|
module Features
|
9
|
+
require 'micro/attributes/features/diff'
|
10
|
+
require 'micro/attributes/features/accept'
|
11
|
+
require 'micro/attributes/features/accept/strict'
|
12
|
+
require 'micro/attributes/features/initialize'
|
13
|
+
require 'micro/attributes/features/initialize/strict'
|
14
|
+
require 'micro/attributes/features/keys_as_symbol'
|
15
|
+
require 'micro/attributes/features/activemodel_validations'
|
16
|
+
|
8
17
|
extend self
|
9
18
|
|
10
19
|
module Name
|
11
20
|
ALL = [
|
12
21
|
DIFF = 'diff'.freeze,
|
22
|
+
ACCEPT = 'accept'.freeze,
|
13
23
|
INITIALIZE = 'initialize'.freeze,
|
14
24
|
KEYS_AS_SYMBOL = 'keys_as_symbol'.freeze,
|
15
25
|
ACTIVEMODEL_VALIDATIONS = 'activemodel_validations'.freeze
|
@@ -19,36 +29,74 @@ module Micro
|
|
19
29
|
module Options
|
20
30
|
KEYS = [
|
21
31
|
DIFF = 'Diff'.freeze,
|
22
|
-
INIT = '
|
23
|
-
|
32
|
+
INIT = 'Initialize'.freeze,
|
33
|
+
ACCEPT = 'Accept'.freeze,
|
34
|
+
INIT_STRICT = 'InitializeStrict'.freeze,
|
35
|
+
ACCEPT_STRICT = 'AcceptStrict'.freeze,
|
24
36
|
KEYS_AS_SYMBOL = 'KeysAsSymbol'.freeze,
|
25
|
-
AM_VALIDATIONS = '
|
37
|
+
AM_VALIDATIONS = 'ActiveModelValidations'.freeze
|
26
38
|
].sort.freeze
|
27
39
|
|
40
|
+
KEYS_TO_FEATURES = {
|
41
|
+
DIFF => Features::Diff,
|
42
|
+
INIT => Features::Initialize,
|
43
|
+
ACCEPT => Features::Accept,
|
44
|
+
INIT_STRICT => Features::Initialize::Strict,
|
45
|
+
ACCEPT_STRICT => Features::Accept::Strict,
|
46
|
+
KEYS_AS_SYMBOL => Features::KeysAsSymbol,
|
47
|
+
AM_VALIDATIONS => Features::ActiveModelValidations
|
48
|
+
}.freeze
|
49
|
+
|
28
50
|
NAMES_TO_KEYS = {
|
29
51
|
Name::DIFF => DIFF,
|
52
|
+
Name::ACCEPT => ACCEPT,
|
30
53
|
Name::INITIALIZE => INIT,
|
31
54
|
Name::KEYS_AS_SYMBOL => KEYS_AS_SYMBOL,
|
32
55
|
Name::ACTIVEMODEL_VALIDATIONS => AM_VALIDATIONS
|
33
56
|
}.freeze
|
34
57
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
58
|
+
INIT_INIT_STRICT = "#{INIT}_#{INIT_STRICT}".freeze
|
59
|
+
ACCEPT_ACCEPT_STRICT = "#{ACCEPT}_#{ACCEPT_STRICT}".freeze
|
60
|
+
|
61
|
+
BuildKey = -> combination do
|
62
|
+
combination.sort.join('_')
|
63
|
+
.sub(INIT_INIT_STRICT, INIT_STRICT)
|
64
|
+
.sub(ACCEPT_ACCEPT_STRICT, ACCEPT_STRICT)
|
65
|
+
end
|
66
|
+
|
67
|
+
KEYS_TO_MODULES = begin
|
68
|
+
combinations = (1..KEYS.size).map { |n| KEYS.combination(n).to_a }.flatten(1).sort_by { |i| "#{i.size}#{i.join}" }
|
69
|
+
combinations.delete_if { |combination| combination.include?(INIT_STRICT) && !combination.include?(INIT) }
|
70
|
+
combinations.delete_if { |combination| combination.include?(ACCEPT_STRICT) && !combination.include?(ACCEPT) }
|
71
|
+
combinations.each_with_object({}) do |combination, features|
|
72
|
+
included = [
|
73
|
+
'def self.included(base)',
|
74
|
+
' base.send(:include, ::Micro::Attributes)',
|
75
|
+
combination.map { |key| " base.send(:include, ::#{KEYS_TO_FEATURES[key].name})" },
|
76
|
+
'end'
|
77
|
+
].flatten.join("\n")
|
78
|
+
|
79
|
+
key = BuildKey.call(combination)
|
80
|
+
|
81
|
+
With.const_set(key, Module.new.tap { |mod| mod.instance_eval(included) })
|
82
|
+
|
83
|
+
features[key] = With.const_get(key, false)
|
84
|
+
end.freeze
|
85
|
+
end
|
86
|
+
|
87
|
+
ACTIVEMODEL_VALIDATION = 'activemodel_validation'.freeze
|
42
88
|
|
43
89
|
def self.fetch_key(arg)
|
44
90
|
if arg.is_a?(Hash)
|
91
|
+
return ACCEPT_STRICT if arg[:accept] == :strict
|
92
|
+
|
45
93
|
INIT_STRICT if arg[:initialize] == :strict
|
46
94
|
else
|
47
|
-
|
95
|
+
str = String(arg)
|
48
96
|
|
49
|
-
|
97
|
+
name = str == ACTIVEMODEL_VALIDATION ? Name::ACTIVEMODEL_VALIDATIONS : str
|
50
98
|
|
51
|
-
NAMES_TO_KEYS[name]
|
99
|
+
KEYS_TO_MODULES.key?(name) ? name : NAMES_TO_KEYS[name]
|
52
100
|
end
|
53
101
|
end
|
54
102
|
|
@@ -65,23 +113,26 @@ module Micro
|
|
65
113
|
yield(keys)
|
66
114
|
end
|
67
115
|
|
68
|
-
def self.
|
69
|
-
keys.delete_if { |key| key == INIT
|
116
|
+
def self.remove_base_if_has_strict(keys)
|
117
|
+
keys.delete_if { |key| key == INIT } if keys.include?(INIT_STRICT)
|
118
|
+
keys.delete_if { |key| key == ACCEPT } if keys.include?(ACCEPT_STRICT)
|
70
119
|
end
|
71
120
|
|
72
121
|
def self.without_keys(keys_to_exclude)
|
73
|
-
(KEYS - keys_to_exclude)
|
74
|
-
|
75
|
-
|
122
|
+
keys = (KEYS - keys_to_exclude)
|
123
|
+
keys.delete_if { |key| key == INIT || key == INIT_STRICT } if keys_to_exclude.include?(INIT)
|
124
|
+
keys.delete_if { |key| key == ACCEPT || key == ACCEPT_STRICT } if keys_to_exclude.include?(ACCEPT)
|
125
|
+
keys
|
76
126
|
end
|
77
127
|
|
78
|
-
def self.fetch_module_by_keys(
|
79
|
-
|
80
|
-
|
81
|
-
option = keys.sort.join('_')
|
128
|
+
def self.fetch_module_by_keys(combination)
|
129
|
+
key = BuildKey.call(combination)
|
82
130
|
|
83
|
-
KEYS_TO_MODULES.fetch(
|
131
|
+
KEYS_TO_MODULES.fetch(key)
|
84
132
|
end
|
133
|
+
|
134
|
+
private_constant :KEYS_TO_FEATURES, :NAMES_TO_KEYS, :INVALID_NAME
|
135
|
+
private_constant :INIT_INIT_STRICT, :ACCEPT_ACCEPT_STRICT, :BuildKey
|
85
136
|
end
|
86
137
|
|
87
138
|
def all
|
@@ -90,17 +141,24 @@ module Micro
|
|
90
141
|
|
91
142
|
def with(names)
|
92
143
|
Options.fetch_keys(names) do |keys|
|
144
|
+
Options.remove_base_if_has_strict(keys)
|
145
|
+
|
93
146
|
Options.fetch_module_by_keys(keys)
|
94
147
|
end
|
95
148
|
end
|
96
149
|
|
97
150
|
def without(names)
|
98
151
|
Options.fetch_keys(names) do |keys|
|
99
|
-
|
152
|
+
keys_to_fetch = Options.without_keys(keys)
|
100
153
|
|
101
|
-
|
154
|
+
return ::Micro::Attributes if keys_to_fetch.empty?
|
155
|
+
|
156
|
+
Options.fetch_module_by_keys(keys_to_fetch)
|
102
157
|
end
|
103
158
|
end
|
159
|
+
|
160
|
+
private_constant :Name
|
104
161
|
end
|
162
|
+
|
105
163
|
end
|
106
164
|
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Micro::Attributes
|
4
|
+
module Features
|
5
|
+
module Accept
|
6
|
+
def attributes_errors
|
7
|
+
@__attributes_errors
|
8
|
+
end
|
9
|
+
|
10
|
+
def attributes_errors?
|
11
|
+
!@__attributes_errors.empty?
|
12
|
+
end
|
13
|
+
|
14
|
+
def rejected_attributes
|
15
|
+
@__rejected_attributes ||= attributes_errors.keys
|
16
|
+
end
|
17
|
+
|
18
|
+
def accepted_attributes
|
19
|
+
@__accepted_attributes ||= defined_attributes - rejected_attributes
|
20
|
+
end
|
21
|
+
|
22
|
+
def rejected_attributes?
|
23
|
+
attributes_errors?
|
24
|
+
end
|
25
|
+
|
26
|
+
def accepted_attributes?
|
27
|
+
!rejected_attributes?
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def __call_before_attributes_assign
|
33
|
+
@__attributes_errors = {}
|
34
|
+
end
|
35
|
+
|
36
|
+
KeepProc = -> validation_data { validation_data[0] == :accept && validation_data[1] == Proc }
|
37
|
+
|
38
|
+
def __attribute_assign(key, initialize_value, attribute_data)
|
39
|
+
validation_data = attribute_data[1]
|
40
|
+
|
41
|
+
value_to_assign = FetchValueToAssign.(initialize_value, attribute_data[0], KeepProc.(validation_data))
|
42
|
+
|
43
|
+
value = __attributes[key] = instance_variable_set("@#{key}", value_to_assign)
|
44
|
+
|
45
|
+
__attribute_accept_or_reject(key, value, validation_data) if !validation_data.empty?
|
46
|
+
end
|
47
|
+
|
48
|
+
def __attribute_accept_or_reject(key, value, validation_data)
|
49
|
+
context = Context.with(key, value, validation_data)
|
50
|
+
|
51
|
+
error_msg = context.rejection_message(Validate.call(context))
|
52
|
+
|
53
|
+
@__attributes_errors[key] = error_msg if error_msg
|
54
|
+
end
|
55
|
+
|
56
|
+
Context = Struct.new(:key, :value, :validation, :expected, :allow_nil, :rejection) do
|
57
|
+
def self.with(key, value, data)
|
58
|
+
new(key, value, data[0], data[1], data[2], data[3])
|
59
|
+
end
|
60
|
+
|
61
|
+
def allow_nil?
|
62
|
+
allow_nil && value.nil?
|
63
|
+
end
|
64
|
+
|
65
|
+
def accept?
|
66
|
+
validation == :accept
|
67
|
+
end
|
68
|
+
|
69
|
+
def rejection_message(default_msg)
|
70
|
+
return unless default_msg
|
71
|
+
|
72
|
+
return default_msg unless rejection || expected.respond_to?(:rejection_message)
|
73
|
+
|
74
|
+
rejection_msg = rejection || expected.rejection_message
|
75
|
+
|
76
|
+
return rejection_msg unless rejection_msg.is_a?(Proc)
|
77
|
+
|
78
|
+
rejection_msg.arity == 0 ? rejection_msg.call : rejection_msg.call(key)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
module Validate
|
83
|
+
module Callable
|
84
|
+
MESSAGE = 'is invalid'.freeze
|
85
|
+
|
86
|
+
def self.call?(exp); exp.respond_to?(:call); end
|
87
|
+
def self.call(exp, val); exp.call(val); end
|
88
|
+
def self.accept_failed(_exp); MESSAGE; end
|
89
|
+
def self.reject_failed(_exp); MESSAGE; end
|
90
|
+
end
|
91
|
+
|
92
|
+
module KindOf
|
93
|
+
def self.call?(exp); exp.is_a?(Class) || exp.is_a?(Module); end
|
94
|
+
def self.call(exp, val); val.kind_of?(exp); end
|
95
|
+
def self.accept_failed(exp); "expected to be a kind of #{exp}"; end
|
96
|
+
def self.reject_failed(exp); "expected to not be a kind of #{exp}"; end
|
97
|
+
end
|
98
|
+
|
99
|
+
module Predicate
|
100
|
+
QUESTION_MARK = '?'.freeze
|
101
|
+
|
102
|
+
def self.call?(exp); exp.is_a?(Symbol) && exp.to_s.end_with?(QUESTION_MARK); end
|
103
|
+
def self.call(exp, val); val.public_send(exp); end
|
104
|
+
def self.accept_failed(exp); "expected to be #{exp}"; end
|
105
|
+
def self.reject_failed(exp); "expected to not be #{exp}"; end
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.with(expected)
|
109
|
+
return Callable if Callable.call?(expected)
|
110
|
+
return KindOf if KindOf.call?(expected)
|
111
|
+
return Predicate if Predicate.call?(expected)
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.call(context)
|
115
|
+
return if context.allow_nil?
|
116
|
+
|
117
|
+
validate = self.with(expected = context.expected)
|
118
|
+
|
119
|
+
return unless validate
|
120
|
+
|
121
|
+
truthy = validate.call(expected, context.value)
|
122
|
+
|
123
|
+
return truthy ? nil : validate.accept_failed(expected) if context.accept?
|
124
|
+
|
125
|
+
validate.reject_failed(expected) if truthy
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
private_constant :KeepProc, :Context, :Validate
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Micro::Attributes
|
4
|
+
module Features
|
5
|
+
module Accept
|
6
|
+
|
7
|
+
module Strict
|
8
|
+
ATTRIBUTES_REJECTED = "One or more attributes were rejected. Errors:\n".freeze
|
9
|
+
|
10
|
+
def __call_after_attributes_assign
|
11
|
+
return unless attributes_errors?
|
12
|
+
|
13
|
+
__raise_error_if_found_attributes_errors
|
14
|
+
end
|
15
|
+
|
16
|
+
def __raise_error_if_found_attributes_errors
|
17
|
+
raise ArgumentError, [
|
18
|
+
ATTRIBUTES_REJECTED,
|
19
|
+
attributes_errors.map { |key, msg| "* #{key.inspect} #{msg}" }.join("\n")
|
20
|
+
].join
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -3,13 +3,45 @@
|
|
3
3
|
module Micro::Attributes
|
4
4
|
module Features
|
5
5
|
module ActiveModelValidations
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
module Standard
|
7
|
+
private def __call_after_attributes_assign
|
8
|
+
run_validations!
|
9
|
+
end
|
10
|
+
end
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
module CheckActivemodelValidationErrors
|
13
|
+
private def __check_activemodel_validation_errors
|
14
|
+
return if errors.blank?
|
15
|
+
|
16
|
+
errors_hash = errors.to_hash
|
17
|
+
|
18
|
+
defined_attributes.each do |key|
|
19
|
+
value = Utils::Hashes.assoc(errors_hash, key)
|
20
|
+
|
21
|
+
@__attributes_errors[key] = value.join(', ') if value.present?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module WithAccept
|
27
|
+
include CheckActivemodelValidationErrors
|
28
|
+
|
29
|
+
private def __call_after_attributes_assign
|
30
|
+
run_validations! unless attributes_errors?
|
31
|
+
|
32
|
+
__check_activemodel_validation_errors
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module WithAcceptStrict
|
37
|
+
include CheckActivemodelValidationErrors
|
38
|
+
|
39
|
+
private def __call_after_attributes_assign
|
40
|
+
__raise_error_if_found_attributes_errors if attributes_errors?
|
41
|
+
|
42
|
+
run_validations!
|
43
|
+
|
44
|
+
__check_activemodel_validation_errors
|
13
45
|
end
|
14
46
|
end
|
15
47
|
|
@@ -22,11 +54,23 @@ module Micro::Attributes
|
|
22
54
|
end
|
23
55
|
end
|
24
56
|
|
25
|
-
|
57
|
+
def self.included(base)
|
58
|
+
begin
|
59
|
+
require 'active_model'
|
60
|
+
|
61
|
+
base.send(:include, ::ActiveModel::Validations)
|
62
|
+
base.extend(ClassMethods)
|
26
63
|
|
27
|
-
|
28
|
-
|
64
|
+
case
|
65
|
+
when base <= Features::Accept::Strict then base.send(:include, WithAcceptStrict)
|
66
|
+
when base <= Features::Accept then base.send(:include, WithAccept)
|
67
|
+
else base.send(:include, Standard)
|
68
|
+
end
|
69
|
+
rescue LoadError
|
29
70
|
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private_constant :Standard, :CheckActivemodelValidationErrors, :WithAccept, :WithAcceptStrict
|
30
74
|
end
|
31
75
|
end
|
32
76
|
end
|
@@ -7,22 +7,17 @@ module Micro::Attributes
|
|
7
7
|
base.class_eval(<<-RUBY)
|
8
8
|
def initialize(arg)
|
9
9
|
self.attributes = arg
|
10
|
-
__call_after_micro_attribute
|
11
10
|
end
|
12
11
|
RUBY
|
13
12
|
end
|
14
13
|
|
15
|
-
def with_attribute(key, val)
|
16
|
-
self.class.new(attributes.merge(key => val))
|
17
|
-
end
|
18
|
-
|
19
14
|
def with_attributes(arg)
|
20
15
|
self.class.new(attributes.merge(arg))
|
21
16
|
end
|
22
17
|
|
23
|
-
|
24
|
-
|
25
|
-
|
18
|
+
def with_attribute(key, val)
|
19
|
+
with_attributes(key => val)
|
20
|
+
end
|
26
21
|
end
|
27
22
|
end
|
28
23
|
end
|
@@ -9,15 +9,15 @@ module Micro::Attributes
|
|
9
9
|
:symbol
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
12
|
+
def __attribute_key_check__(value)
|
13
13
|
Kind::Of.(::Symbol, value)
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
16
|
+
def __attribute_key_transform__(value)
|
17
17
|
value
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
20
|
+
def __attributes_keys_transform__(hash)
|
21
21
|
Utils::Hashes.kind(hash)
|
22
22
|
end
|
23
23
|
end
|
@@ -11,15 +11,15 @@ module Micro
|
|
11
11
|
:indifferent
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def __attribute_key_check__(value)
|
15
15
|
value
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def __attribute_key_transform__(value)
|
19
19
|
value.to_s
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
22
|
+
def __attributes_keys_transform__(hash)
|
23
23
|
Utils::Hashes.stringify_keys(hash)
|
24
24
|
end
|
25
25
|
|
@@ -32,18 +32,54 @@ module Micro
|
|
32
32
|
@__attributes_required__ ||= Set.new
|
33
33
|
end
|
34
34
|
|
35
|
-
def __attributes_required_add(name,
|
36
|
-
if
|
35
|
+
def __attributes_required_add(name, opt, hasnt_default)
|
36
|
+
if opt[:required] || (attributes_are_all_required? && hasnt_default)
|
37
37
|
__attributes_required__.add(name)
|
38
38
|
end
|
39
39
|
|
40
40
|
nil
|
41
41
|
end
|
42
42
|
|
43
|
-
|
44
|
-
|
43
|
+
module Options
|
44
|
+
PERMITTED = [
|
45
|
+
:default, :required,
|
46
|
+
:validate, :validates, # activemodel_validations
|
47
|
+
:accept, :reject, :allow_nil, :rejection_message # accept
|
48
|
+
].freeze
|
45
49
|
|
46
|
-
|
50
|
+
INVALID_MESSAGE = [
|
51
|
+
"Found one or more invalid options: %{invalid_options}\n\nThe valid ones are: ",
|
52
|
+
PERMITTED.map { |key| ":#{key}" }.join(', ')
|
53
|
+
].join.freeze
|
54
|
+
|
55
|
+
def self.check(opt)
|
56
|
+
invalid_keys = opt.keys - PERMITTED
|
57
|
+
|
58
|
+
return if invalid_keys.empty?
|
59
|
+
|
60
|
+
invalid_options = { invalid_options: invalid_keys.inspect.tr('[', '').tr(']', '') }
|
61
|
+
|
62
|
+
raise ArgumentError, (INVALID_MESSAGE % invalid_options)
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.for_accept(opt)
|
66
|
+
allow_nil = opt[:allow_nil]
|
67
|
+
rejection_message = opt[:rejection_message]
|
68
|
+
|
69
|
+
return [:accept, opt[:accept], allow_nil, rejection_message] if opt.key?(:accept)
|
70
|
+
return [:reject, opt[:reject], allow_nil, rejection_message] if opt.key?(:reject)
|
71
|
+
|
72
|
+
Kind::Empty::ARRAY
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def __attributes_data_to_assign(name, opt)
|
77
|
+
hasnt_default = !opt.key?(:default)
|
78
|
+
|
79
|
+
[
|
80
|
+
hasnt_default ? __attributes_required_add(name, opt, hasnt_default) : opt[:default],
|
81
|
+
Options.for_accept(opt)
|
82
|
+
]
|
47
83
|
end
|
48
84
|
|
49
85
|
def __attributes
|
@@ -56,15 +92,18 @@ module Micro
|
|
56
92
|
attr_reader(name)
|
57
93
|
end
|
58
94
|
|
59
|
-
def __attribute_assign(key, can_overwrite,
|
60
|
-
name =
|
95
|
+
def __attribute_assign(key, can_overwrite, opt)
|
96
|
+
name = __attribute_key_check__(__attribute_key_transform__(key))
|
97
|
+
|
98
|
+
Options.check(opt)
|
99
|
+
|
61
100
|
has_attribute = attribute?(name)
|
62
101
|
|
63
102
|
__attribute_reader(name) unless has_attribute
|
64
103
|
|
65
|
-
__attributes_data__[name] = __attributes_data_to_assign(name,
|
104
|
+
__attributes_data__[name] = __attributes_data_to_assign(name, opt) if can_overwrite || !has_attribute
|
66
105
|
|
67
|
-
__call_after_attribute_assign__(name,
|
106
|
+
__call_after_attribute_assign__(name, opt)
|
68
107
|
end
|
69
108
|
|
70
109
|
def __call_after_attribute_assign__(attr_name, options); end
|
@@ -72,12 +111,20 @@ module Micro
|
|
72
111
|
# NOTE: can't be renamed! It is used by u-case v4.
|
73
112
|
def __attributes_set_after_inherit__(arg)
|
74
113
|
arg.each do |key, val|
|
75
|
-
|
114
|
+
opt = if default = val[0]
|
115
|
+
requ_key, requ_val = val[1]
|
116
|
+
|
117
|
+
hash = requ_key ? { requ_key => requ_val } : {}
|
118
|
+
hash[:default] = default
|
119
|
+
hash
|
120
|
+
end
|
121
|
+
|
122
|
+
__attribute_assign(key, true, opt || Kind::Empty::HASH)
|
76
123
|
end
|
77
124
|
end
|
78
125
|
|
79
126
|
def attribute?(name)
|
80
|
-
__attributes.member?(
|
127
|
+
__attributes.member?(__attribute_key_transform__(name))
|
81
128
|
end
|
82
129
|
|
83
130
|
def attribute(name, options = Kind::Empty::HASH)
|
@@ -112,7 +159,7 @@ module Micro
|
|
112
159
|
private_constant :WRONG_NUMBER_OF_ARGS
|
113
160
|
end
|
114
161
|
|
115
|
-
private_constant :ForSubclasses
|
162
|
+
private_constant :Options, :ForSubclasses
|
116
163
|
end
|
117
164
|
|
118
165
|
private_constant :Macros
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: u-attributes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rodrigo Serradura
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-09-
|
11
|
+
date: 2020-09-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: kind
|
@@ -81,6 +81,8 @@ files:
|
|
81
81
|
- lib/micro/attributes.rb
|
82
82
|
- lib/micro/attributes/diff.rb
|
83
83
|
- lib/micro/attributes/features.rb
|
84
|
+
- lib/micro/attributes/features/accept.rb
|
85
|
+
- lib/micro/attributes/features/accept/strict.rb
|
84
86
|
- lib/micro/attributes/features/activemodel_validations.rb
|
85
87
|
- lib/micro/attributes/features/diff.rb
|
86
88
|
- lib/micro/attributes/features/initialize.rb
|
@@ -89,7 +91,6 @@ files:
|
|
89
91
|
- lib/micro/attributes/macros.rb
|
90
92
|
- lib/micro/attributes/utils.rb
|
91
93
|
- lib/micro/attributes/version.rb
|
92
|
-
- lib/micro/attributes/with.rb
|
93
94
|
- lib/u-attributes.rb
|
94
95
|
- test.sh
|
95
96
|
- u-attributes.gemspec
|
@@ -1,182 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'micro/attributes/features/diff'
|
4
|
-
require 'micro/attributes/features/initialize'
|
5
|
-
require 'micro/attributes/features/initialize/strict'
|
6
|
-
require 'micro/attributes/features/keys_as_symbol'
|
7
|
-
require 'micro/attributes/features/activemodel_validations'
|
8
|
-
|
9
|
-
|
10
|
-
module Micro
|
11
|
-
module Attributes
|
12
|
-
module With
|
13
|
-
#
|
14
|
-
# Features
|
15
|
-
#
|
16
|
-
module Diff
|
17
|
-
def self.included(base)
|
18
|
-
base.send(:include, ::Micro::Attributes)
|
19
|
-
base.send(:include, ::Micro::Attributes::Features::Diff)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
module Initialize
|
24
|
-
def self.included(base)
|
25
|
-
base.send(:include, ::Micro::Attributes)
|
26
|
-
base.send(:include, ::Micro::Attributes::Features::Initialize)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
module StrictInitialize
|
31
|
-
def self.included(base)
|
32
|
-
base.send(:include, Initialize)
|
33
|
-
base.send(:include, ::Micro::Attributes::Features::Initialize::Strict)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
module KeysAsSymbol
|
38
|
-
def self.included(base)
|
39
|
-
base.send(:include, ::Micro::Attributes)
|
40
|
-
base.send(:include, ::Micro::Attributes::Features::KeysAsSymbol)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
module ActiveModelValidations
|
45
|
-
def self.included(base)
|
46
|
-
base.send(:include, Initialize)
|
47
|
-
base.send(:include, ::Micro::Attributes::Features::ActiveModelValidations)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
#
|
52
|
-
# Combinations
|
53
|
-
#
|
54
|
-
module AMValidations_Diff
|
55
|
-
def self.included(base)
|
56
|
-
base.send(:include, ActiveModelValidations)
|
57
|
-
base.send(:include, ::Micro::Attributes::Features::Diff)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
module AMValidations_Diff_Init
|
62
|
-
def self.included(base)
|
63
|
-
base.send(:include, ActiveModelValidations)
|
64
|
-
base.send(:include, ::Micro::Attributes::Features::Diff)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
module AMValidations_Diff_Init_KeysAsSymbol
|
69
|
-
def self.included(base)
|
70
|
-
base.send(:include, ActiveModelValidations)
|
71
|
-
base.send(:include, ::Micro::Attributes::Features::Diff)
|
72
|
-
base.send(:include, ::Micro::Attributes::Features::KeysAsSymbol)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
module AMValidations_Diff_InitStrict
|
77
|
-
def self.included(base)
|
78
|
-
base.send(:include, AMValidations_Diff_Init)
|
79
|
-
base.send(:include, ::Micro::Attributes::Features::Initialize::Strict)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
module AMValidations_Diff_InitStrict_KeysAsSymbol
|
84
|
-
def self.included(base)
|
85
|
-
base.send(:include, AMValidations_Diff_Init)
|
86
|
-
base.send(:include, ::Micro::Attributes::Features::Initialize::Strict)
|
87
|
-
base.send(:include, ::Micro::Attributes::Features::KeysAsSymbol)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
module AMValidations_Diff_KeysAsSymbol
|
92
|
-
def self.included(base)
|
93
|
-
base.send(:include, AMValidations_Diff)
|
94
|
-
base.send(:include, ::Micro::Attributes::Features::KeysAsSymbol)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
module AMValidations_Init
|
99
|
-
def self.included(base)
|
100
|
-
base.send(:include, ActiveModelValidations)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
module AMValidations_Init_KeysAsSymbol
|
105
|
-
def self.included(base)
|
106
|
-
base.send(:include, AMValidations_Init)
|
107
|
-
base.send(:include, ::Micro::Attributes::Features::KeysAsSymbol)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
module AMValidations_InitStrict
|
112
|
-
def self.included(base)
|
113
|
-
base.send(:include, ActiveModelValidations)
|
114
|
-
base.send(:include, ::Micro::Attributes::Features::Initialize::Strict)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
module AMValidations_InitStrict_KeysAsSymbol
|
119
|
-
def self.included(base)
|
120
|
-
base.send(:include, AMValidations_InitStrict)
|
121
|
-
base.send(:include, ::Micro::Attributes::Features::KeysAsSymbol)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
module AMValidations_KeysAsSymbol
|
126
|
-
def self.included(base)
|
127
|
-
base.send(:include, ActiveModelValidations)
|
128
|
-
base.send(:include, ::Micro::Attributes::Features::KeysAsSymbol)
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
module Diff_Init
|
133
|
-
def self.included(base)
|
134
|
-
base.send(:include, Initialize)
|
135
|
-
base.send(:include, ::Micro::Attributes::Features::Diff)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
module Diff_Init_KeysAsSymbol
|
140
|
-
def self.included(base)
|
141
|
-
base.send(:include, Diff_Init)
|
142
|
-
base.send(:include, ::Micro::Attributes::Features::KeysAsSymbol)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
module Diff_InitStrict
|
147
|
-
def self.included(base)
|
148
|
-
base.send(:include, Diff_Init)
|
149
|
-
base.send(:include, ::Micro::Attributes::Features::Initialize::Strict)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
module Diff_InitStrict_KeysAsSymbol
|
154
|
-
def self.included(base)
|
155
|
-
base.send(:include, Diff_InitStrict)
|
156
|
-
base.send(:include, ::Micro::Attributes::Features::KeysAsSymbol)
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
module Diff_KeysAsSymbol
|
161
|
-
def self.included(base)
|
162
|
-
base.send(:include, Diff)
|
163
|
-
base.send(:include, ::Micro::Attributes::Features::KeysAsSymbol)
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
module Init_KeysAsSymbol
|
168
|
-
def self.included(base)
|
169
|
-
base.send(:include, Initialize)
|
170
|
-
base.send(:include, ::Micro::Attributes::Features::KeysAsSymbol)
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
module InitStrict_KeysAsSymbol
|
175
|
-
def self.included(base)
|
176
|
-
base.send(:include, StrictInitialize)
|
177
|
-
base.send(:include, ::Micro::Attributes::Features::KeysAsSymbol)
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|