hanami-validations 2.0.0.beta4 → 2.0.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 +8 -0
- data/README.md +15 -422
- data/hanami-validations.gemspec +2 -1
- data/lib/hanami/validations/form.rb +1 -37
- data/lib/hanami/validations/version.rb +4 -1
- data/lib/hanami/validations.rb +27 -28
- data/lib/hanami/validator.rb +1 -0
- data/lib/hanami-validations.rb +3 -0
- metadata +26 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a0d6367d5ae641a10c53578dba401c026a6e7b125210312a18a8f9f1430093e
|
4
|
+
data.tar.gz: 22891e60e1235640d73b896acda9961764255bf219f76cc3107f884ea4fc27b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1aa7f299bed7884008b0325870fc40143e838e6af4b498bd6979e676198cd8166e04d987cb31ac619d39a14851ab04b825e192865bed4c571cd01243197e9f7
|
7
|
+
data.tar.gz: 3854da5422fe1c48aa839fa3cefa58b7f93c7ea5115d8ad15601e82561245cb10de27fc8810fe416b56e43d9c0c11ae2c26506b56bf625d40c74e82fa7b52226
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Hanami::Validations
|
2
2
|
|
3
|
-
|
3
|
+
Internal support gem for `Hanami::Action` params validation.
|
4
4
|
|
5
5
|
## Status
|
6
6
|
|
@@ -51,437 +51,30 @@ $ gem install hanami-validations
|
|
51
51
|
|
52
52
|
## Usage
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
### Overview
|
58
|
-
|
59
|
-
The main object provided by this gem is `Hanami::Validator`.
|
60
|
-
It providers a powerful DSL to define a validation contract, which is made of a schema and optional rules.
|
61
|
-
|
62
|
-
A validation **schema** is a set of steps that filters, coerces, and checks the validity of incoming data.
|
63
|
-
Validation **rules** are a set of directives, to check if business rules are respected.
|
64
|
-
|
65
|
-
Only when the input is formally valid (according to the **schema**), validation **rules** are checked.
|
66
|
-
|
67
|
-
```ruby
|
68
|
-
# frozen_string_literal: true
|
69
|
-
|
70
|
-
require "hanami/validations"
|
71
|
-
|
72
|
-
class SignupValidator < Hanami::Validator
|
73
|
-
schema do
|
74
|
-
required(:email).value(:string)
|
75
|
-
required(:age).value(:integer)
|
76
|
-
end
|
77
|
-
|
78
|
-
rule(:age) do
|
79
|
-
key.failure("must be greater than 18") if value < 18
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
validator = SignupValidator.new
|
84
|
-
|
85
|
-
result = validator.call(email: "user@hanamirb.test", age: 37)
|
86
|
-
result.success? # => true
|
87
|
-
|
88
|
-
result = validator.call(email: "user@hanamirb.test", age: "foo")
|
89
|
-
result.success? # => false
|
90
|
-
result.errors.to_h # => {:age=>["must be an integer"]}
|
91
|
-
|
92
|
-
result = validator.call(email: "user@hanamirb.test", age: 17)
|
93
|
-
puts result.success? # => false
|
94
|
-
puts result.errors.to_h # => {:age=>["must be greater than 18"]}
|
95
|
-
```
|
96
|
-
|
97
|
-
### Schemas
|
98
|
-
|
99
|
-
A basic schema doesn't apply data coercion, input must already have the right Ruby types.
|
100
|
-
|
101
|
-
```ruby
|
102
|
-
# frozen_string_literal: true
|
103
|
-
|
104
|
-
require "hanami/validations"
|
105
|
-
|
106
|
-
class SignupValidator < Hanami::Validator
|
107
|
-
schema do
|
108
|
-
required(:email).value(:string)
|
109
|
-
required(:age).value(:integer)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
validator = SignupValidator.new
|
114
|
-
|
115
|
-
result = validator.call(email: "user@hanamirb.test", age: 37)
|
116
|
-
puts result.success? # => true
|
117
|
-
|
118
|
-
result = validator.call(email: "user@hanamirb.test", age: "37")
|
119
|
-
puts result.success? # => false
|
120
|
-
puts result.errors.to_h # => {:age=>["must be an integer"]}
|
121
|
-
```
|
122
|
-
|
123
|
-
### Params
|
124
|
-
|
125
|
-
When used in _params mode_, a schema applies data coercion, before to run validation checks.
|
126
|
-
|
127
|
-
This is designed for Web form/HTTP params.
|
128
|
-
|
129
|
-
```ruby
|
130
|
-
# frozen_string_literal: true
|
131
|
-
|
132
|
-
require "bundler/setup"
|
133
|
-
require "hanami/validations"
|
134
|
-
|
135
|
-
class SignupValidator < Hanami::Validator
|
136
|
-
params do
|
137
|
-
required(:email).value(:string)
|
138
|
-
required(:age).value(:integer)
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
validator = SignupValidator.new
|
143
|
-
|
144
|
-
result = validator.call(email: "user@hanamirb.test", age: "37")
|
145
|
-
puts result.success? # => true
|
146
|
-
puts result.to_h # => {:email=>"user@hanamirb.test", :age=>37}
|
147
|
-
```
|
148
|
-
|
149
|
-
### JSON
|
150
|
-
|
151
|
-
When used in _JSON mode_, data coercions are still applied, but they follow different policies.
|
152
|
-
For instance, because JSON supports integers, strings won't be coerced into integers.
|
153
|
-
|
154
|
-
```ruby
|
155
|
-
# frozen_string_literal: true
|
156
|
-
|
157
|
-
require "hanami/validations"
|
158
|
-
|
159
|
-
class SignupValidator < Hanami::Validator
|
160
|
-
json do
|
161
|
-
required(:email).value(:string)
|
162
|
-
required(:age).value(:integer)
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
validator = SignupValidator.new
|
167
|
-
|
168
|
-
result = validator.call(email: "user@hanamirb.test", age: 37)
|
169
|
-
puts result.success? # => true
|
170
|
-
puts result.to_h # => {:email=>"user@hanamirb.test", :age=>37}
|
171
|
-
|
172
|
-
result = validator.call(email: "user@hanamirb.test", age: "37")
|
173
|
-
puts result.success? # => false
|
174
|
-
```
|
175
|
-
|
176
|
-
### Whitelisting
|
177
|
-
|
178
|
-
Unknown keys from incoming data are filtered out:
|
179
|
-
|
180
|
-
```ruby
|
181
|
-
# frozen_string_literal: true
|
182
|
-
|
183
|
-
require "hanami/validations"
|
184
|
-
|
185
|
-
class SignupValidator < Hanami::Validator
|
186
|
-
schema do
|
187
|
-
required(:email).value(:string)
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
validator = SignupValidator.new
|
192
|
-
|
193
|
-
result = validator.call(email: "user@hanamirb.test", foo: "bar")
|
194
|
-
puts result.success? # => true
|
195
|
-
puts result.to_h # => {:email=>"user@hanamirb.test"}
|
196
|
-
```
|
197
|
-
|
198
|
-
### Custom Types
|
199
|
-
|
200
|
-
```ruby
|
201
|
-
# frozen_string_literal: true
|
202
|
-
|
203
|
-
require "hanami/validations"
|
204
|
-
|
205
|
-
module Types
|
206
|
-
include Dry::Types()
|
207
|
-
|
208
|
-
StrippedString = Types::String.constructor(&:strip)
|
209
|
-
end
|
210
|
-
|
211
|
-
class SignupValidator < Hanami::Validator
|
212
|
-
params do
|
213
|
-
required(:email).value(Types::StrippedString)
|
214
|
-
required(:age).value(:integer)
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
validator = SignupValidator.new
|
219
|
-
|
220
|
-
result = validator.call(email: " user@hanamirb.test ", age: "37")
|
221
|
-
puts result.success? # => true
|
222
|
-
puts result.to_h # => {:email=>"user@hanamirb.test", :age=>37}
|
223
|
-
```
|
224
|
-
|
225
|
-
### Rules
|
226
|
-
|
227
|
-
Rules are performing a set of domain-specific validation checks.
|
228
|
-
Rules are executed only after the validations from the schema are satisfied.
|
229
|
-
|
230
|
-
```ruby
|
231
|
-
# frozen_string_literal: true
|
232
|
-
|
233
|
-
require "hanami/validations"
|
234
|
-
|
235
|
-
class EventValidator < Hanami::Validator
|
236
|
-
params do
|
237
|
-
required(:start_date).value(:date)
|
238
|
-
end
|
239
|
-
|
240
|
-
rule(:start_date) do
|
241
|
-
key.failure("must be in the future") if value <= Date.today
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
validator = EventValidator.new
|
246
|
-
|
247
|
-
result = validator.call(start_date: "foo")
|
248
|
-
puts result.success? # => false
|
249
|
-
puts result.errors.to_h # => {:start_date=>["must be a date"]}
|
250
|
-
|
251
|
-
result = validator.call(start_date: Date.today)
|
252
|
-
puts result.success? # => false
|
253
|
-
puts result.errors.to_h # => {:start_date=>["must be in the future"]}
|
254
|
-
|
255
|
-
result = validator.call(start_date: Date.today + 1)
|
256
|
-
puts result.success? # => true
|
257
|
-
puts result.to_h # => {:start_date=>#<Date: 2019-07-03 ((2458668j,0s,0n),+0s,2299161j)>}
|
258
|
-
```
|
259
|
-
|
260
|
-
Learn more about rules: https://dry-rb.org/gems/dry-validation/master/rules/
|
261
|
-
|
262
|
-
### Inheritance
|
263
|
-
|
264
|
-
Schema and rules validations can be inherited and used by subclasses
|
54
|
+
Installing hanami-validations enables support for `params` validation in
|
55
|
+
[hanami-controller][controller]’s `Hanami::Action` classes.
|
265
56
|
|
266
57
|
```ruby
|
267
|
-
|
268
|
-
|
269
|
-
require "hanami/validations"
|
270
|
-
|
271
|
-
class ApplicationValidator < Hanami::Validator
|
58
|
+
class Signup < Hanami::Action
|
272
59
|
params do
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
class SignupValidator < ApplicationValidator
|
278
|
-
params do
|
279
|
-
required(:user).hash do
|
280
|
-
required(:email).filled(:string)
|
281
|
-
end
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
|
-
validator = SignupValidator.new
|
286
|
-
|
287
|
-
result = validator.call(user: { email: "user@hanamirb.test" }, _csrf_token: "abc123")
|
288
|
-
puts result.success? # => true
|
289
|
-
puts result.to_h # => {:user=>{:email=>"user@hanamirb.test"}, :_csrf_token=>"abc123"}
|
290
|
-
```
|
291
|
-
|
292
|
-
### Messages
|
293
|
-
|
294
|
-
Failure messages can be hardcoded or refer to a message template system.
|
295
|
-
`hanami-validations` supports natively a default YAML based message template system, or alternatively, `i18n` gem.
|
296
|
-
|
297
|
-
We have already seen rule failures set with hardcoded messages, here's an example of how to use keys to refer to interpolated messages.
|
298
|
-
|
299
|
-
```ruby
|
300
|
-
# frozen_string_literal: true
|
301
|
-
|
302
|
-
require "hanami/validations"
|
303
|
-
|
304
|
-
class ApplicationValidator < Hanami::Validator
|
305
|
-
config.messages.top_namespace = "bookshelf"
|
306
|
-
config.messages.load_paths << "config/errors.yml"
|
307
|
-
end
|
308
|
-
```
|
309
|
-
|
310
|
-
In the `ApplicationValidator` there is defined the application namespace (`"bookshelf"`), which is the root of the messages file.
|
311
|
-
Below that top name, there is the key `errors`. Everything that is nested here is accessible by the validations.
|
312
|
-
|
313
|
-
There are two ways to organize messages:
|
314
|
-
|
315
|
-
1. Right below `errors`. This is for **general purposes** error messages (e.g. `bookshelf` => `errors` => `taken`)
|
316
|
-
2. Below `errors` => `rules` => name of the attribute => custom key (e.g. `bookshelf` => `errors` => `age` => `invalid`). This is for **specific** messages that affect only a specific attribute.
|
317
|
-
|
318
|
-
Our **suggestion** is to start with **specific** messages and see if there is a need to generalize them.
|
319
|
-
|
320
|
-
```yaml
|
321
|
-
# config/errors.yml
|
322
|
-
en:
|
323
|
-
bookshelf:
|
324
|
-
errors:
|
325
|
-
taken: "oh noes, it's already taken"
|
326
|
-
network: "there is a network error (%{code})"
|
327
|
-
rules:
|
328
|
-
age:
|
329
|
-
invalid: "must be greater than 18"
|
330
|
-
email:
|
331
|
-
invalid: "not a valid email"
|
332
|
-
```
|
333
|
-
|
334
|
-
#### General purpose messages
|
335
|
-
|
336
|
-
```ruby
|
337
|
-
class SignupValidator < ApplicationValidator
|
338
|
-
schema do
|
339
|
-
required(:username).filled(:string)
|
340
|
-
end
|
341
|
-
|
342
|
-
rule(:username) do
|
343
|
-
key.failure(:taken) if values[:username] == "jodosha"
|
344
|
-
end
|
345
|
-
end
|
346
|
-
|
347
|
-
validator = SignupValidator.new
|
348
|
-
|
349
|
-
result = validator.call(username: "foo")
|
350
|
-
puts result.success? # => true
|
351
|
-
|
352
|
-
result = validator.call(username: "jodosha")
|
353
|
-
puts result.success? # => false
|
354
|
-
puts result.errors.to_h # => {:username=>["oh noes, it's already taken"]}
|
355
|
-
```
|
356
|
-
|
357
|
-
#### Specific messages
|
358
|
-
|
359
|
-
Please note that the failure key used it's the same for both the attributes (`:invalid`), but thanks to the nesting, the library is able to lookup the right message.
|
360
|
-
|
361
|
-
```ruby
|
362
|
-
class SignupValidator < ApplicationValidator
|
363
|
-
schema do
|
364
|
-
required(:email).filled(:string)
|
365
|
-
required(:age).filled(:integer)
|
366
|
-
end
|
367
|
-
|
368
|
-
rule(:email) do
|
369
|
-
key.failure(:invalid) unless values[:email] =~ /@/
|
60
|
+
required(:first_name)
|
61
|
+
required(:last_name)
|
62
|
+
required(:email)
|
370
63
|
end
|
371
64
|
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
end
|
376
|
-
|
377
|
-
validator = SignupValidator.new
|
378
|
-
|
379
|
-
result = validator.call(email: "foo", age: 17)
|
380
|
-
puts result.success? # => false
|
381
|
-
puts result.errors.to_h # => {:email=>["not a valid email"], :age=>["must be greater than 18"]}
|
382
|
-
```
|
383
|
-
|
384
|
-
#### Extra information
|
65
|
+
def handle(req, *)
|
66
|
+
puts req.params.class # => Signup::Params
|
67
|
+
puts req.params.class.superclass # => Hanami::Action::Params
|
385
68
|
|
386
|
-
|
387
|
-
|
388
|
-
```ruby
|
389
|
-
class RefundValidator < ApplicationValidator
|
390
|
-
schema do
|
391
|
-
required(:refunded_code).filled(:string)
|
392
|
-
end
|
393
|
-
|
394
|
-
rule(:refunded_code) do
|
395
|
-
key.failure(:network, code: "123") if values[:refunded_code] == "error"
|
69
|
+
puts req.params[:first_name] # => "Luca"
|
70
|
+
puts req.params[:admin] # => nil
|
396
71
|
end
|
397
72
|
end
|
398
|
-
|
399
|
-
validator = RefundValidator.new
|
400
|
-
|
401
|
-
result = validator.call(refunded_code: "error")
|
402
|
-
puts result.success? # => false
|
403
|
-
puts result.errors.to_h # => {:refunded_code=>["there is a network error (123)"]}
|
404
73
|
```
|
405
74
|
|
406
|
-
|
407
|
-
|
408
|
-
### External dependencies
|
409
|
-
|
410
|
-
If the validator needs to plug one or more objects to run the validations, there is a DSL to do so: `:option`.
|
411
|
-
When the validator is instantiated, the declared dependencies must be passed.
|
412
|
-
|
413
|
-
```ruby
|
414
|
-
# frozen_string_literal: true
|
415
|
-
|
416
|
-
require "hanami/validations"
|
417
|
-
|
418
|
-
class AddressValidator
|
419
|
-
def valid?(value)
|
420
|
-
value.match(/Rome/)
|
421
|
-
end
|
422
|
-
end
|
423
|
-
|
424
|
-
class DeliveryValidator < Hanami::Validator
|
425
|
-
option :address_validator
|
426
|
-
|
427
|
-
schema do
|
428
|
-
required(:address).filled(:string)
|
429
|
-
end
|
430
|
-
|
431
|
-
rule(:address) do
|
432
|
-
key.failure("not a valid address") unless address_validator.valid?(values[:address])
|
433
|
-
end
|
434
|
-
end
|
435
|
-
|
436
|
-
validator = DeliveryValidator.new(address_validator: AddressValidator.new)
|
437
|
-
|
438
|
-
result = validator.call(address: "foo")
|
439
|
-
puts result.success? # => false
|
440
|
-
puts result.errors.to_h # => {:address=>["not a valid address"]}
|
441
|
-
```
|
442
|
-
|
443
|
-
Read more about external dependencies: https://dry-rb.org/gems/dry-validation/master/external-dependencies/
|
444
|
-
|
445
|
-
### Mixin
|
446
|
-
|
447
|
-
`hanami-validations` 1.x used to ship a mixin `Hanami::Validations` to be included in classes to provide validation rules.
|
448
|
-
The 2.x series, still ships this mixin, but it will be probably removed in 3.x.
|
449
|
-
|
450
|
-
```ruby
|
451
|
-
# frozen_string_literal: true
|
452
|
-
|
453
|
-
require "hanami/validations"
|
454
|
-
|
455
|
-
class UserValidator
|
456
|
-
include Hanami::Validations
|
457
|
-
|
458
|
-
validations do
|
459
|
-
required(:number).filled(:integer, eql?: 23)
|
460
|
-
end
|
461
|
-
end
|
462
|
-
|
463
|
-
result = UserValidator.new(number: 23).validate
|
464
|
-
|
465
|
-
puts result.success? # => true
|
466
|
-
puts result.to_h # => {:number=>23}
|
467
|
-
puts result.errors.to_h # => {}
|
468
|
-
|
469
|
-
result = UserValidator.new(number: 11).validate
|
470
|
-
|
471
|
-
puts result.success? # => true
|
472
|
-
puts result.to_h # => {:number=>21}
|
473
|
-
puts result.errors.to_h # => {:number=>["must be equal to 23"]}
|
474
|
-
```
|
475
|
-
|
476
|
-
## FAQs
|
477
|
-
### Uniqueness Validation
|
478
|
-
|
479
|
-
Uniqueness validation isn't implemented by `Hanami::Validations` because the context of execution is completely decoupled from persistence.
|
480
|
-
Please remember that **uniqueness validation is a huge race condition between application and the database, and it doesn't guarantee records uniqueness for real.** To effectively enforce this policy you can use SQL database constraints.
|
481
|
-
|
482
|
-
Please read more at: [The Perils of Uniqueness Validations](http://robots.thoughtbot.com/the-perils-of-uniqueness-validations).
|
75
|
+
See [hanami-controller][controller] for more detail on params validation.
|
483
76
|
|
484
|
-
|
77
|
+
[controller]: http://github.com/hanami/controller
|
485
78
|
|
486
79
|
## Contributing
|
487
80
|
|
@@ -493,6 +86,6 @@ If you need to implement it, please use the External dependencies feature (see a
|
|
493
86
|
|
494
87
|
## Copyright
|
495
88
|
|
496
|
-
Copyright © 2014-
|
89
|
+
Copyright © 2014-2022 Hanami Team – Released under MIT License
|
497
90
|
|
498
91
|
This project was formerly known as Lotus (`lotus-validations`).
|
data/hanami-validations.gemspec
CHANGED
@@ -20,7 +20,8 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.metadata["rubygems_mfa_required"] = "true"
|
21
21
|
spec.required_ruby_version = ">= 3.0"
|
22
22
|
|
23
|
-
spec.add_dependency "dry-validation", "
|
23
|
+
spec.add_dependency "dry-validation", ">= 1.10", "< 2"
|
24
|
+
spec.add_dependency "zeitwerk", "~> 2.6.0"
|
24
25
|
|
25
26
|
spec.add_development_dependency "bundler", ">= 1.6", "< 3"
|
26
27
|
spec.add_development_dependency "rake", "~> 13"
|
@@ -4,38 +4,8 @@ module Hanami
|
|
4
4
|
module Validations
|
5
5
|
# Validations mixin for forms/HTTP params.
|
6
6
|
#
|
7
|
-
# This must be used when the input comes from a browser or an HTTP endpoint.
|
8
|
-
# It knows how to deal with common data types, and common edge cases like blank strings.
|
9
|
-
#
|
10
7
|
# @since 0.6.0
|
11
|
-
#
|
12
|
-
# @example
|
13
|
-
# require "hanami/validations/form"
|
14
|
-
#
|
15
|
-
# class Signup
|
16
|
-
# include Hanami::Validations::Form
|
17
|
-
#
|
18
|
-
# validations do
|
19
|
-
# required(:name).filled(:string)
|
20
|
-
# optional(:location).filled(:string)
|
21
|
-
# end
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# result = Signup.new("location" => "Rome").validate
|
25
|
-
# result.success? # => false
|
26
|
-
#
|
27
|
-
# result = Signup.new("name" => "Luca").validate
|
28
|
-
# result.success? # => true
|
29
|
-
#
|
30
|
-
# # it works with symbol keys too
|
31
|
-
# result = Signup.new(location: "Rome").validate
|
32
|
-
# result.success? # => false
|
33
|
-
#
|
34
|
-
# result = Signup.new(name: "Luca").validate
|
35
|
-
# result.success? # => true
|
36
|
-
#
|
37
|
-
# result = Signup.new(name: "Luca", location: "Rome").validate
|
38
|
-
# result.success? # => true
|
8
|
+
# @api private
|
39
9
|
module Form
|
40
10
|
# @since 2.0.0
|
41
11
|
# @api private
|
@@ -45,14 +15,8 @@ module Hanami
|
|
45
15
|
end
|
46
16
|
end
|
47
17
|
|
48
|
-
# Override Ruby's hook for modules.
|
49
|
-
#
|
50
|
-
# @param klass [Class] the target action
|
51
|
-
#
|
52
18
|
# @since 0.6.0
|
53
19
|
# @api private
|
54
|
-
#
|
55
|
-
# @see http://www.ruby-doc.org/core/Module.html#method-i-included
|
56
20
|
def self.included(klass)
|
57
21
|
super
|
58
22
|
|
data/lib/hanami/validations.rb
CHANGED
@@ -2,15 +2,34 @@
|
|
2
2
|
|
3
3
|
require "dry/validation"
|
4
4
|
require "delegate"
|
5
|
+
require "zeitwerk"
|
5
6
|
|
7
|
+
# @see Hanami::Validations
|
8
|
+
# @since 0.1.0
|
6
9
|
module Hanami
|
7
10
|
# @since 0.1.0
|
11
|
+
# @api private
|
8
12
|
module Validations
|
9
|
-
|
13
|
+
# @since 2.0.0
|
14
|
+
# @api private
|
15
|
+
def self.gem_loader
|
16
|
+
@gem_loader ||= Zeitwerk::Loader.new.tap do |loader|
|
17
|
+
root = File.expand_path("..", __dir__)
|
18
|
+
loader.tag = "hanami-validations"
|
19
|
+
loader.inflector = Zeitwerk::GemInflector.new("#{root}/hanami-validations.rb")
|
20
|
+
loader.push_dir(root)
|
21
|
+
loader.ignore(
|
22
|
+
"#{root}/hanami-validations.rb",
|
23
|
+
"#{root}/hanami/validations/version.rb"
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
10
27
|
|
11
|
-
|
12
|
-
|
28
|
+
gem_loader.setup
|
29
|
+
require_relative "validations/version"
|
13
30
|
|
31
|
+
# @since 0.1.0
|
32
|
+
# @api private
|
14
33
|
def self.included(klass)
|
15
34
|
super
|
16
35
|
klass.extend(ClassMethods)
|
@@ -35,37 +54,14 @@ module Hanami
|
|
35
54
|
# Validations DSL
|
36
55
|
#
|
37
56
|
# @since 0.1.0
|
57
|
+
# @api private
|
38
58
|
module ClassMethods
|
39
59
|
# Define validation rules from the given block.
|
40
60
|
#
|
41
61
|
# @param blk [Proc] validation rules
|
42
62
|
#
|
43
63
|
# @since 0.6.0
|
44
|
-
#
|
45
|
-
# @see https://guides.hanamirb.org/validations/overview
|
46
|
-
#
|
47
|
-
# @example Basic Example
|
48
|
-
# require "hanami/validations"
|
49
|
-
#
|
50
|
-
# class Signup
|
51
|
-
# include Hanami::Validations
|
52
|
-
#
|
53
|
-
# validations do
|
54
|
-
# required(:name).filled(:string)
|
55
|
-
# end
|
56
|
-
# end
|
57
|
-
#
|
58
|
-
# result = Signup.new(name: "Luca").validate
|
59
|
-
#
|
60
|
-
# result.success? # => true
|
61
|
-
# result.messages # => []
|
62
|
-
# result.output # => {:name=>""}
|
63
|
-
#
|
64
|
-
# result = Signup.new(name: "").validate
|
65
|
-
#
|
66
|
-
# result.success? # => false
|
67
|
-
# result.messages # => {:name=>["must be filled"]}
|
68
|
-
# result.output # => {:name=>""}
|
64
|
+
# @api private
|
69
65
|
def validations(&blk)
|
70
66
|
@_validator = Dry::Validation::Contract.build { schema(&blk) }
|
71
67
|
end
|
@@ -82,6 +78,7 @@ module Hanami
|
|
82
78
|
# @param input [#to_h] a set of input data
|
83
79
|
#
|
84
80
|
# @since 0.6.0
|
81
|
+
# @api private
|
85
82
|
def initialize(input)
|
86
83
|
@input = input
|
87
84
|
end
|
@@ -91,6 +88,7 @@ module Hanami
|
|
91
88
|
# @return [Hanami::Validations::Result]
|
92
89
|
#
|
93
90
|
# @since 0.2.4
|
91
|
+
# @api private
|
94
92
|
def validate
|
95
93
|
Result.new(
|
96
94
|
self.class._validator.call(@input)
|
@@ -103,6 +101,7 @@ module Hanami
|
|
103
101
|
# @return [Hash]
|
104
102
|
#
|
105
103
|
# @since 0.1.0
|
104
|
+
# @api private
|
106
105
|
def to_h
|
107
106
|
validate.to_h
|
108
107
|
end
|
data/lib/hanami/validator.rb
CHANGED
metadata
CHANGED
@@ -1,35 +1,49 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hanami-validations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luca Guidi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-validation
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '1.9'
|
20
17
|
- - ">="
|
21
18
|
- !ruby/object:Gem::Version
|
22
|
-
version: 1.
|
19
|
+
version: '1.10'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '2'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.10'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: zeitwerk
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
26
36
|
requirements:
|
27
37
|
- - "~>"
|
28
38
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
30
|
-
|
39
|
+
version: 2.6.0
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
31
45
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
46
|
+
version: 2.6.0
|
33
47
|
- !ruby/object:Gem::Dependency
|
34
48
|
name: bundler
|
35
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -103,6 +117,7 @@ files:
|
|
103
117
|
- LICENSE.md
|
104
118
|
- README.md
|
105
119
|
- hanami-validations.gemspec
|
120
|
+
- lib/hanami-validations.rb
|
106
121
|
- lib/hanami/validations.rb
|
107
122
|
- lib/hanami/validations/form.rb
|
108
123
|
- lib/hanami/validations/version.rb
|
@@ -123,9 +138,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
123
138
|
version: '3.0'
|
124
139
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
140
|
requirements:
|
126
|
-
- - "
|
141
|
+
- - ">="
|
127
142
|
- !ruby/object:Gem::Version
|
128
|
-
version:
|
143
|
+
version: '0'
|
129
144
|
requirements: []
|
130
145
|
rubygems_version: 3.3.7
|
131
146
|
signing_key:
|