attribeauty 0.3.4 → 0.4.1
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 +10 -0
- data/Gemfile.lock +1 -1
- data/README.md +52 -14
- data/lib/attribeauty/params.rb +13 -14
- data/lib/attribeauty/validator.rb +35 -41
- data/lib/attribeauty/version.rb +1 -1
- data/lib/attribeauty.rb +1 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a594dd2b01526d1b89bea9ceeea3217bf0cb311b236981be2e77bd03dc1b5b2f
|
4
|
+
data.tar.gz: 4f79df9cca230c2c0c29c34746f381818535095383c54902e8a7b90f8ea205de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ab16692f1f34715726b3777889c5ee4f1797eeff0431ce73a116c7e02c5faac34d0453188f2469938b1c98076e172dd37e5b18a5a2c1bff009bb483c067a984
|
7
|
+
data.tar.gz: 78f5e064bc51b85fbb57877ce9bd9a7d3894f7798fdfd7dcfe0dc7989fad2618f3d0358e22467d02351745710b92e81227f6b243a74254e90d377be474b1655a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.4.1] - 2024-06-25
|
4
|
+
|
5
|
+
- Global default_args in accept, to apply your conditions to all attributes
|
6
|
+
|
7
|
+
## [0.4.0] - 2024-06-25
|
8
|
+
|
9
|
+
- Breaking change:
|
10
|
+
- `:allow_nil`, and `:allow_empty` have been replaced with `:exclude_if`
|
11
|
+
- see readme for details
|
12
|
+
|
3
13
|
## [0.3.4] - 2024-06-24
|
4
14
|
|
5
15
|
- tiny refactor
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -103,17 +103,18 @@ class MyController
|
|
103
103
|
|
104
104
|
def update_params
|
105
105
|
params_filter.accept do
|
106
|
-
attribute :title, :string,
|
106
|
+
attribute :title, :string, required: true
|
107
107
|
attribute :email do
|
108
|
-
attribute :address, :string
|
109
|
-
attribute :valid, :boolean
|
110
|
-
attribute :ip_address, :string,
|
108
|
+
attribute :address, :string
|
109
|
+
attribute :valid, :boolean
|
110
|
+
attribute :ip_address, :string, exclude_if: :empty?
|
111
111
|
end
|
112
112
|
end
|
113
113
|
end
|
114
114
|
```
|
115
115
|
|
116
|
-
If you have a "head" param, like in rails, you can exclude it
|
116
|
+
If you have a "head" param, like in rails, you can exclude it, also note the `exclude_if` option, this will exclude the value completely, if it evaluates to true.
|
117
|
+
`exclude_if` will accept a single method call (`:nil?`) or an array (`[:nil?, :empty?]`)
|
117
118
|
|
118
119
|
```
|
119
120
|
class MyController
|
@@ -126,7 +127,7 @@ class MyController
|
|
126
127
|
private
|
127
128
|
|
128
129
|
# your params look like this:
|
129
|
-
# { user: { title: "woo", email: { address: "hmm@yep.com" } } }
|
130
|
+
# { user: { title: "woo", email: { address: "hmm@yep.com", ip_address: "" } } }
|
130
131
|
#
|
131
132
|
def params_filter
|
132
133
|
Attribeauty::Params.with(request.params)
|
@@ -138,11 +139,11 @@ class MyController
|
|
138
139
|
def update_params
|
139
140
|
params_filter.accept do
|
140
141
|
container :user do
|
141
|
-
attribute :title, :string,
|
142
|
+
attribute :title, :string, required: true
|
142
143
|
attribute :email do
|
143
|
-
attribute :address, :string,
|
144
|
-
attribute :valid, :boolean
|
145
|
-
attribute :ip_address, :string,
|
144
|
+
attribute :address, :string, exclude_if: [:empty?, :nil?]
|
145
|
+
attribute :valid, :boolean
|
146
|
+
attribute :ip_address, :string, exclude_if: :empty?
|
146
147
|
end
|
147
148
|
end
|
148
149
|
end
|
@@ -177,11 +178,48 @@ class MyController
|
|
177
178
|
def update_params
|
178
179
|
params_filter.accept! do
|
179
180
|
container :user do
|
180
|
-
attribute :title, :string,
|
181
|
+
attribute :title, :string, exclude_if: :nil?, required: true
|
181
182
|
attribute :email do
|
182
|
-
attribute :address, :string
|
183
|
-
attribute :valid, :boolean
|
184
|
-
attribute :ip_address, :string
|
183
|
+
attribute :address, :string
|
184
|
+
attribute :valid, :boolean
|
185
|
+
attribute :ip_address, :string
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
```
|
193
|
+
|
194
|
+
what if you want to require all attributes? If you pass the `required: true` or `exclude_if: :nil?` with the `accept`, it will be applied to all attributes.
|
195
|
+
|
196
|
+
```
|
197
|
+
class MyController
|
198
|
+
def update
|
199
|
+
MyRecord.update(update_params)
|
200
|
+
|
201
|
+
redirect_to index_path
|
202
|
+
end
|
203
|
+
|
204
|
+
private
|
205
|
+
|
206
|
+
# your params look like this:
|
207
|
+
# { user: { profile: [{ address: { street_name: "Main St" } }] } }
|
208
|
+
#
|
209
|
+
def params_filter
|
210
|
+
Attribeauty::Params.with(request.params)
|
211
|
+
end
|
212
|
+
|
213
|
+
# exclude_if and required will be passed onto all attributes
|
214
|
+
#
|
215
|
+
def update_params
|
216
|
+
params_filter.accept exclude_if: :nil?, required: true do
|
217
|
+
container :user do
|
218
|
+
attribute :title, :string,
|
219
|
+
attribute :email do
|
220
|
+
attribute :address, :string
|
221
|
+
attribute :valid, :boolean
|
222
|
+
attribute :ip_address, :string
|
185
223
|
end
|
186
224
|
end
|
187
225
|
end
|
data/lib/attribeauty/params.rb
CHANGED
@@ -10,15 +10,16 @@ module Attribeauty
|
|
10
10
|
new(request_params)
|
11
11
|
end
|
12
12
|
|
13
|
-
attr_reader :
|
13
|
+
attr_reader :prefix, :request_params, :acceptables, :to_h, :errors, :strict, :default_args
|
14
14
|
|
15
15
|
def initialize(request_params)
|
16
|
-
@request_params = request_params.transform_keys(&:to_sym)
|
16
|
+
@request_params = (request_params || {}).transform_keys(&:to_sym)
|
17
17
|
@to_h = {}
|
18
18
|
@errors = []
|
19
19
|
end
|
20
20
|
|
21
|
-
def accept(&)
|
21
|
+
def accept(**args, &)
|
22
|
+
@default_args = args
|
22
23
|
instance_eval(&)
|
23
24
|
|
24
25
|
raise MissingAttributeError, errors.join(", ") if errors.any? && strict?
|
@@ -26,10 +27,10 @@ module Attribeauty
|
|
26
27
|
self
|
27
28
|
end
|
28
29
|
|
29
|
-
def accept!(&)
|
30
|
+
def accept!(**args, &)
|
30
31
|
@strict = true
|
31
32
|
|
32
|
-
accept(&)
|
33
|
+
accept(**args, &)
|
33
34
|
end
|
34
35
|
|
35
36
|
def to_hash = to_h
|
@@ -47,7 +48,6 @@ module Attribeauty
|
|
47
48
|
#
|
48
49
|
def attribute(name, type = nil, **args, &block)
|
49
50
|
value = request_params[name]
|
50
|
-
return if required?(value, **args)
|
51
51
|
return hash_from_nested(name, value, &block) if block_given?
|
52
52
|
|
53
53
|
value_from_validator(name, value, type, **args)
|
@@ -67,29 +67,28 @@ module Attribeauty
|
|
67
67
|
|
68
68
|
private
|
69
69
|
|
70
|
-
def required?(value, **args)
|
71
|
-
value.nil? && args[:required].nil?
|
72
|
-
end
|
73
|
-
|
74
70
|
def value_from_validator(name, value, type, **args)
|
75
|
-
|
71
|
+
merged_args = args.merge(default_args || {})
|
72
|
+
validator = Validator.run(name, value, type, **merged_args)
|
76
73
|
@errors.push(*validator.errors)
|
77
74
|
@to_h[name.to_sym] = validator.value if validator.valid?
|
78
75
|
end
|
79
76
|
|
80
77
|
def hash_from_nested(name, value, &block)
|
81
|
-
|
78
|
+
result =
|
82
79
|
if value.is_a?(Array)
|
83
80
|
value.map do |val|
|
84
|
-
params = self.class.with(val).accept(&block)
|
81
|
+
params = self.class.with(val).accept(**default_args, &block)
|
85
82
|
@errors.push(*params.errors)
|
86
83
|
params.to_h
|
87
84
|
end.reject(&:empty?)
|
88
85
|
else
|
89
|
-
params = self.class.with(value).accept(&block)
|
86
|
+
params = self.class.with(value).accept(**default_args, &block)
|
90
87
|
@errors.push(*params.errors)
|
91
88
|
params.to_h
|
92
89
|
end
|
90
|
+
|
91
|
+
@to_h[name.to_sym] = result unless result.empty?
|
93
92
|
end
|
94
93
|
end
|
95
94
|
end
|
@@ -2,39 +2,36 @@
|
|
2
2
|
|
3
3
|
module Attribeauty
|
4
4
|
class Validator
|
5
|
-
ALLOWS_HASH = {
|
6
|
-
allow_nil: :nil?,
|
7
|
-
allow_empty: :empty?
|
8
|
-
}.freeze
|
9
|
-
|
10
5
|
def self.run(name, type, original_val, **args)
|
11
6
|
new(name, type, original_val, **args).run
|
12
7
|
end
|
13
8
|
|
14
|
-
attr_reader :original_val, :errors, :name, :type, :required, :default, :
|
9
|
+
attr_reader :original_val, :errors, :name, :type, :required, :default, :excludes, :value, :valid
|
15
10
|
|
16
11
|
def initialize(name, original_val, type = nil, **args)
|
17
12
|
@name = name
|
18
13
|
@type = type
|
19
14
|
@original_val = original_val
|
20
15
|
@default = args[:default]
|
21
|
-
|
22
|
-
@
|
16
|
+
args.delete_if { |key, value| key == :required && value == false }
|
17
|
+
@required = args[:required]
|
18
|
+
@excludes = args[:exclude_if]
|
23
19
|
|
24
20
|
@valid = true
|
25
21
|
@errors = []
|
26
22
|
end
|
27
23
|
|
28
24
|
def run
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
25
|
+
handle_missing_original_val!
|
26
|
+
handle_missing_required!
|
27
|
+
handle_missing_type
|
28
|
+
|
29
|
+
set_default
|
30
|
+
cast_value
|
31
|
+
handle_excludes
|
37
32
|
|
33
|
+
self
|
34
|
+
rescue ValueInvalidError
|
38
35
|
self
|
39
36
|
end
|
40
37
|
|
@@ -42,49 +39,46 @@ module Attribeauty
|
|
42
39
|
valid
|
43
40
|
end
|
44
41
|
|
42
|
+
def required?
|
43
|
+
required
|
44
|
+
end
|
45
|
+
|
45
46
|
private
|
46
47
|
|
47
|
-
def
|
48
|
-
return unless
|
48
|
+
def handle_missing_original_val!
|
49
|
+
return unless !required? && original_val.nil?
|
49
50
|
|
50
|
-
@
|
51
|
-
|
52
|
-
|
53
|
-
def cast_value
|
54
|
-
@value = TypeCaster.run(original_val, type)
|
51
|
+
@valid = false
|
52
|
+
raise ValueInvalidError
|
55
53
|
end
|
56
54
|
|
57
55
|
# only returning errors if required is missing, not if nil?, or :empty?
|
58
|
-
def handle_missing_required
|
56
|
+
def handle_missing_required!
|
59
57
|
return unless required? && original_val.nil?
|
60
58
|
|
61
59
|
errors << "#{name} required"
|
62
60
|
@valid = false
|
61
|
+
raise ValueInvalidError
|
63
62
|
end
|
64
63
|
|
65
|
-
def
|
66
|
-
|
67
|
-
|
68
|
-
@valid = !value.public_send(predicate)
|
64
|
+
def handle_missing_type
|
65
|
+
@value = original_val if type.nil?
|
69
66
|
end
|
70
67
|
|
71
|
-
def
|
72
|
-
|
73
|
-
end
|
68
|
+
def set_default
|
69
|
+
return unless original_val.nil? && !default.nil?
|
74
70
|
|
75
|
-
|
76
|
-
|
77
|
-
# NOTE: only one will be checked, if you pass both:
|
78
|
-
# allow_nil and allow_empty, one will be ignored
|
79
|
-
def predicate
|
80
|
-
return if allows.empty?
|
71
|
+
@original_val = default
|
72
|
+
end
|
81
73
|
|
82
|
-
|
83
|
-
|
74
|
+
def cast_value
|
75
|
+
@value ||= TypeCaster.run(original_val, type)
|
84
76
|
end
|
85
77
|
|
86
|
-
def
|
87
|
-
|
78
|
+
def handle_excludes
|
79
|
+
return if excludes.nil? || !valid?
|
80
|
+
|
81
|
+
@valid = ![*excludes].flatten.any? { |exclude| value.public_send(exclude) }
|
88
82
|
end
|
89
83
|
end
|
90
84
|
end
|
data/lib/attribeauty/version.rb
CHANGED
data/lib/attribeauty.rb
CHANGED