hanami-validations 0.0.0 → 0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cf76bc3940612ffdc8aa64e07941219547ca0c32
4
- data.tar.gz: 04ad62428f8e83fa41ec449f84bd38ade15d0345
3
+ metadata.gz: adeb97811a77f27c28ac940395e0fab28c0670c0
4
+ data.tar.gz: d6bc2be331bde334ff930692e1b66458b08f04c5
5
5
  SHA512:
6
- metadata.gz: 17a5e5c9f565fd7101ed62a12883d2ecb8c8467d5a0c2da0f081030ea3b0066a1f6119d38b17b97fb24b944058264ae1ee06c4e23ae48cf33305fb51403146e6
7
- data.tar.gz: 4863bd75a0ce12a0e4ef59ede8d24959917b6d20b469d29cf6ac5ebdcadccd4c4c1e2dee68dd59d0418c398509d9d9711493848dd73f19b2dc06d3937702f5da
6
+ metadata.gz: 5fb1f27b1db7511d4b2cbb926acba8650596615c171901d27c2dcc5c5c5d6ed55ff0edb41c47d267441b98c07780ec90eb900ebc3d4240c78e55f05f07762eeb
7
+ data.tar.gz: 517a5991fae90f9c8b83fe0dbf96ad9e86ff93ac0898c9b8fc296da16547a78d9fbb7d8341772fc9e32bdc4454f507cf59a382e9c386202b0c5485fa4c15468e
data/CHANGELOG.md ADDED
@@ -0,0 +1,89 @@
1
+ # Hanami::Validations
2
+ Validations mixin for Ruby objects
3
+
4
+ ## v0.5.0 - 2016-01-22
5
+ ### Changed
6
+ - [Luca Guidi] Renamed the project
7
+
8
+ ## v0.4.0 - 2016-01-12
9
+ ## Changed
10
+ - [Hélio Costa e Silva & Luca Guidi] Ignore blank values for format and size validation
11
+
12
+ ### Fixed
13
+ - [Pascal Betz] Ensure acceptance validation to reject blank strings
14
+
15
+ ## v0.3.3 - 2015-09-30
16
+ ### Added
17
+ - [Luca Guidi] Official support for JRuby 9k+
18
+
19
+ ## v0.3.2 - 2015-05-22
20
+ ### Added
21
+ - [deepj] Introduced `Lotus::Validations#invalid?`
22
+
23
+ ## v0.3.1 - 2015-05-15
24
+ ### Fixed
25
+ - [Luca Guidi] Fixed Hash serialization for nested validations. It always return nested `::Hash` structure.
26
+ - [Alfonso Uceda Pompa & Dmitry Tymchuk] Fixed Hash serialization when `Lotus::Entity` is included in the same class.
27
+
28
+ ## v0.3.0 - 2015-03-23
29
+
30
+ ## v0.2.4 - 2015-01-30
31
+ ### Added
32
+ - [Steve Hodgkiss] Introduced `Lotus::Validations::Error#attribute_name`
33
+ - [Steve Hodgkiss] Nested validations
34
+
35
+ ### Changed
36
+ - [Steve Hodgkiss] `Lotus::Validations::Error#name` returns the complete attribute name (Eg. `first_name` or `address.street`)
37
+
38
+ ## v0.2.3 - 2015-01-12
39
+ ### Added
40
+ - [Luca Guidi] Compatibility with Lotus::Entity
41
+
42
+ ### Fixed
43
+ - [Luca Guidi] Ensure `.validates` usage to not raise `ArgumentError` when `:type` option is passed
44
+ - [Luca Guidi] Ensure to assign attributes when only `.validates` is used
45
+
46
+ ## v0.2.2 - 2015-01-08
47
+ ### Added
48
+ - [Steve Hodgkiss] Introduced `Validations.validates`. It defines validations, for already existing attributes.
49
+
50
+ ## v0.2.1 - 2014-12-23
51
+ ### Added
52
+ - [Luca Guidi] Introduced `Validations::Errors#to_h` and `to_a`
53
+ - [Luca Guidi] Introduced `Validations::Errors#any?`
54
+ - [Luca Guidi] Official support for Ruby 2.2
55
+
56
+ ### Fixed
57
+ - [Satoshi Amemiya] Made `Validations#valid?` idempotent
58
+
59
+ ## v0.2.0 - 2014-11-23
60
+ ### Added
61
+ - [Luca Guidi] Skip attribute whitelisting when a validator does not define any attribute
62
+ - [Luca Guidi] Official support for Rubinius 2.3+
63
+ - [Luca Guidi] Implemented `#each` in order to allow bulk operations on attributes
64
+ - [Luca Guidi] Implemented `#to_h` to make validations usable by other libraries
65
+ - [Luca Guidi] Made `#initialize` to accept Hashes with strings as keys, but only for declared attributes
66
+ - [Luca Guidi] Lazy coercions, from now on `valid?` is not required to obtain a coerced value from a single attribute
67
+ - [Rik Tonnard] Made validators reusable by allowing infinite inclusion
68
+
69
+ ## v0.1.0 - 2014-10-23
70
+ ### Added
71
+ - [Luca Guidi] Made `#initialize` to accept any object that implements `#to_h`
72
+ - [Luca Guidi] Custom coercions for user defined classes
73
+ - [Luca Guidi] Raise an exception at the load time when a validation is not recognized
74
+ - [Luca Guidi] Allow validators inheritance
75
+ - [Luca Guidi] Confirmation validation
76
+ - [Luca Guidi] Exclusion validation
77
+ - [Luca Guidi] Size validation
78
+ - [Luca Guidi] Acceptance validation
79
+ - [Jeremy Stephens] Inclusion validation
80
+ - [Luca Guidi] Format validation
81
+ - [Luca Guidi] Presence validation
82
+ - [Luca Guidi] Coercions
83
+ - [Luca Guidi] Basic module inclusion
84
+ - [Luca Guidi] Official support for JRuby 1.7+ (with 2.0 mode)
85
+ - [Luca Guidi] Official support for MRI 2.0+
86
+
87
+ ### Fixed
88
+ - [Jeremy Stephens] Ensure to not fail validations when coerce falsey values
89
+ - [Luca Guidi] Ensure `Lotus::Validations#valid?` to be idempotent
data/LICENSE.md ADDED
@@ -0,0 +1,22 @@
1
+ Copyright © 2014-2016 Luca Guidi
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,8 +1,28 @@
1
1
  # Hanami::Validations
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/hanami/validations`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Validations mixins for objects
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ ## Status
6
+
7
+ [![Gem Version](http://img.shields.io/gem/v/hanami-validations.svg)](https://badge.fury.io/rb/hanami-validations)
8
+ [![Build Status](http://img.shields.io/travis/hanami/validations/master.svg)](https://travis-ci.org/hanami/validations?branch=master)
9
+ [![Coverage](http://img.shields.io/coveralls/hanami/validations/master.svg)](https://coveralls.io/r/hanami/validations)
10
+ [![Code Climate](http://img.shields.io/codeclimate/github/hanami/validations.svg)](https://codeclimate.com/github/hanami/validations)
11
+ [![Dependencies](http://img.shields.io/gemnasium/hanami/validations.svg)](https://gemnasium.com/hanami/validations)
12
+ [![Inline Docs](http://inch-ci.org/github/hanami/validations.svg)](http://inch-ci.org/github/hanami/validations)
13
+
14
+ ## Contact
15
+
16
+ * Home page: http://hanamirb.org
17
+ * Mailing List: http://hanamirb.org/mailing-list
18
+ * API Doc: http://rdoc.info/gems/hanami-validations
19
+ * Bugs/Issues: https://github.com/hanami/validations/issues
20
+ * Support: http://stackoverflow.com/questions/tagged/hanami
21
+ * Chat: http://chat.hanamirb.org
22
+
23
+ ## Rubies
24
+
25
+ __Hanami::Validations__ supports Ruby (MRI) 2+, JRuby 9k+
6
26
 
7
27
  ## Installation
8
28
 
@@ -22,15 +42,547 @@ Or install it yourself as:
22
42
 
23
43
  ## Usage
24
44
 
25
- TODO: Write usage instructions here
45
+ `Hanami::Validations` is a set of lightweight validations for Ruby objects.
46
+
47
+ ### Attributes
48
+
49
+ The framework allows you to define attributes for each object.
50
+
51
+ It defines an initializer, whose attributes can be passed as a hash.
52
+ All unknown values are ignored, which is useful for whitelisting attributes.
53
+
54
+ ```ruby
55
+ require 'hanami/validations'
56
+
57
+ class Person
58
+ include Hanami::Validations
59
+
60
+ attribute :name, presence: true
61
+ attribute :email, presence: true
62
+ end
63
+
64
+ person = Person.new(name: 'Luca', email: 'me@example.org', age: 32)
65
+ person.name # => "Luca"
66
+ person.email # => "me@example.org"
67
+ person.age # => raises NoMethodError because `:age` wasn't defined as attribute.
68
+ ```
69
+
70
+ #### Blank Values
71
+
72
+ The framework will treat as valid any blank attributes, __without__ `presence`, for both `format` and `size` predicates.
73
+
74
+ ```ruby
75
+ require 'hanami/validations'
76
+
77
+ class Person
78
+ include Hanami::Validations
79
+
80
+ attribute :name, type: String, size: 5..45
81
+ attribute :email, type: String, size: 20..80, format: /@/
82
+ attribute :skills, type: Array, size: 1..3
83
+ attribute :keys, type: Hash, size: 1..3
84
+ end
85
+
86
+ Person.new.valid? # < true
87
+ Person.new(name: '').valid? # < true
88
+ Person.new(skills: '').valid? # < true
89
+ Person.new(skills: ['ruby', 'hanami']).valid? # < true
90
+
91
+ Person.new(skills: []).valid? # < false
92
+ Person.new(keys: {}).valid? # < false
93
+ Person.new(keys: {a: :b}, skills: []).valid? # < false
94
+ ```
95
+
96
+ If you want to _disable_ this behaviour, please, refer to [presence](https://github.com/hanami/validations#presence).
97
+
98
+ ### Validations
99
+
100
+ If you prefer Hanami::Validations to **only define validations**, but **not attributes**,
101
+ you can use the following alternative syntax.
102
+
103
+ ```ruby
104
+ require 'hanami/validations'
105
+
106
+ class Person
107
+ include Hanami::Validations
108
+ attr_accessor :name, :email
109
+
110
+ # Custom initializer
111
+ def initialize(attributes = {})
112
+ @name, @email = attributes.values_at(:name, :email)
113
+ end
114
+
115
+ validates :name, presence: true
116
+ validates :email, presence: true
117
+ end
118
+
119
+ person = Person.new(name: 'Luca', email: 'me@example.org')
120
+ person.name # => "Luca"
121
+ person.email # => "me@example.org"
122
+ ```
123
+
124
+ This is a bit more verbose, but offers a great level of flexibility for your
125
+ Ruby objects. It also allows to use Hanami::Validations in combination with
126
+ **other frameworks**.
127
+
128
+ ### Coercions
129
+
130
+ If a Ruby class is passed to the `:type` option, the given value is coerced, accordingly.
131
+
132
+ #### Standard coercions
133
+
134
+ ```ruby
135
+ require 'hanami/validations'
136
+
137
+ class Person
138
+ include Hanami::Validations
139
+
140
+ attribute :fav_number, type: Integer
141
+ end
142
+
143
+ person = Person.new(fav_number: '23')
144
+ person.valid?
145
+
146
+ person.fav_number # => 23
147
+ ```
148
+
149
+ Allowed types are:
150
+
151
+ * `Array`
152
+ * `BigDecimal`
153
+ * `Boolean`
154
+ * `Date`
155
+ * `DateTime`
156
+ * `Float`
157
+ * `Hash`
158
+ * `Integer`
159
+ * `Pathname`
160
+ * `Set`
161
+ * `String`
162
+ * `Symbol`
163
+ * `Time`
164
+
165
+ #### Custom coercions
166
+
167
+ If a user defined class is specified, it can be freely used for coercion purposes.
168
+ The only limitation is that the constructor should have **arity of 1**.
169
+
170
+ ```ruby
171
+ require 'hanami/validations'
172
+
173
+ class FavNumber
174
+ def initialize(number)
175
+ @number = number
176
+ end
177
+ end
178
+
179
+ class BirthDate
180
+ end
181
+
182
+ class Person
183
+ include Hanami::Validations
184
+
185
+ attribute :fav_number, type: FavNumber
186
+ attribute :date, type: BirthDate
187
+ end
188
+
189
+ person = Person.new(fav_number: '23', date: 'Oct 23, 2014')
190
+ person.valid?
191
+
192
+ person.fav_number # => #<FavNumber:0x007ffc644bba00 @number="23">
193
+ person.date # => this raises an error, because BirthDate#initialize doesn't accept any arg
194
+ ```
195
+
196
+ ### Validations
197
+
198
+ Each attribute definition can receive a set of options to define one or more
199
+ validations.
200
+
201
+ **Validations are triggered when you invoke `#valid?`.**
202
+
203
+ #### Acceptance
204
+
205
+ An attribute is valid if its value is _truthy_.
206
+
207
+ ```ruby
208
+ require 'hanami/validations'
209
+
210
+ class Signup
211
+ include Hanami::Validations
212
+
213
+ attribute :terms_of_service, acceptance: true
214
+ end
215
+
216
+ signup = Signup.new(terms_of_service: '1')
217
+ signup.valid? # => true
218
+
219
+ signup = Signup.new(terms_of_service: 'true')
220
+ signup.valid? # => true
221
+
222
+ signup = Signup.new(terms_of_service: '')
223
+ signup.valid? # => false
224
+
225
+ signup = Signup.new(terms_of_service: '0')
226
+ signup.valid? # => false
227
+ ```
228
+
229
+ #### Confirmation
230
+
231
+ An attribute is valid if its value and the value of a corresponding attribute
232
+ is valid.
233
+
234
+ By convention, if you have a `password` attribute, the validation looks for `password_confirmation`.
235
+
236
+ ```ruby
237
+ require 'hanami/validations'
238
+
239
+ class Signup
240
+ include Hanami::Validations
241
+
242
+ attribute :password, confirmation: true
243
+ end
244
+
245
+ signup = Signup.new(password: 'secret', password_confirmation: 'secret')
246
+ signup.valid? # => true
247
+
248
+ signup = Signup.new(password: 'secret', password_confirmation: 'x')
249
+ signup.valid? # => false
250
+ ```
251
+
252
+ #### Exclusion
253
+
254
+ An attribute is valid, if the value isn't excluded from the value described by
255
+ the validator.
256
+
257
+ The validator value can be anything that responds to `#include?`.
258
+ In Ruby, this includes most of the core objects: `String`, `Enumerable` (`Array`, `Hash`,
259
+ `Range`, `Set`).
260
+
261
+ See also [Inclusion](#inclusion).
262
+
263
+ ```ruby
264
+ require 'hanami/validations'
265
+
266
+ class Signup
267
+ include Hanami::Validations
268
+
269
+ attribute :music, exclusion: ['pop']
270
+ end
271
+
272
+ signup = Signup.new(music: 'rock')
273
+ signup.valid? # => true
274
+
275
+ signup = Signup.new(music: 'pop')
276
+ signup.valid? # => false
277
+ ```
278
+
279
+ #### Format
280
+
281
+ An attribute is valid if it matches the given Regular Expression.
282
+
283
+ ```ruby
284
+ require 'hanami/validations'
285
+
286
+ class Signup
287
+ include Hanami::Validations
288
+
289
+ attribute :name, format: /\A[a-zA-Z]+\z/
290
+ end
26
291
 
27
- ## Development
292
+ signup = Signup.new(name: 'Luca')
293
+ signup.valid? # => true
28
294
 
29
- After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
295
+ signup = Signup.new(name: '23')
296
+ signup.valid? # => false
297
+ ```
298
+
299
+ #### Inclusion
300
+
301
+ An attribute is valid, if the value provided is included in the validator's
302
+ value.
303
+
304
+ The validator value can be anything that responds to `#include?`.
305
+ In Ruby, this includes most of the core objects: like `String`, `Enumerable` (`Array`, `Hash`,
306
+ `Range`, `Set`).
307
+
308
+ See also [Exclusion](#exclusion).
309
+
310
+ ```ruby
311
+ require 'prime'
312
+ require 'hanami/validations'
313
+
314
+ class PrimeNumbers
315
+ def initialize(limit)
316
+ @numbers = Prime.each(limit).to_a
317
+ end
318
+
319
+ def include?(number)
320
+ @numbers.include?(number)
321
+ end
322
+ end
323
+
324
+ class Signup
325
+ include Hanami::Validations
326
+
327
+ attribute :age, inclusion: 18..99
328
+ attribute :fav_number, inclusion: PrimeNumbers.new(100)
329
+ end
330
+
331
+ signup = Signup.new(age: 32)
332
+ signup.valid? # => true
333
+
334
+ signup = Signup.new(age: 17)
335
+ signup.valid? # => false
336
+
337
+ signup = Signup.new(fav_number: 23)
338
+ signup.valid? # => true
339
+
340
+ signup = Signup.new(fav_number: 8)
341
+ signup.valid? # => false
342
+ ```
343
+
344
+ #### Presence
345
+
346
+ An attribute is valid if present.
347
+
348
+ ```ruby
349
+ require 'hanami/validations'
350
+
351
+ class Signup
352
+ include Hanami::Validations
353
+
354
+ attribute :name, presence: true
355
+ end
356
+
357
+ signup = Signup.new(name: 'Luca')
358
+ signup.valid? # => true
359
+
360
+ signup = Signup.new(name: '')
361
+ signup.valid? # => false
362
+
363
+ signup = Signup.new(name: nil)
364
+ signup.valid? # => false
365
+ ```
366
+
367
+ #### Size
368
+
369
+ An attribute is valid if its `#size` falls within the described value.
370
+
371
+ ```ruby
372
+ require 'hanami/validations'
373
+
374
+ class Signup
375
+ MEGABYTE = 1024 ** 2
376
+ include Hanami::Validations
377
+
378
+ attribute :ssn, size: 11 # exact match
379
+ attribute :password, size: 8..64 # range
380
+ attribute :avatar, size: 1..(5 * MEGABYTE)
381
+ end
382
+
383
+ signup = Signup.new(password: 'a-very-long-password')
384
+ signup.valid? # => true
385
+
386
+ signup = Signup.new(password: 'short')
387
+ signup.valid? # => false
388
+ ```
389
+
390
+ **Note that in the example above you are able to validate the weight of the file,
391
+ because Ruby's `File` and `Tempfile` both respond to `#size`.**
392
+
393
+ #### Uniqueness
394
+
395
+ Uniqueness validations aren't implemented because this library doesn't deal with persistence.
396
+ The other reason is that this isn't an effective way to ensure uniqueness of a value in a database.
397
+
398
+ Please read more at: [The Perils of Uniqueness Validations](http://robots.thoughtbot.com/the-perils-of-uniqueness-validations).
399
+
400
+ ### Nested validations
401
+
402
+ Nested validations are handled with a nested block syntax.
403
+
404
+ ```ruby
405
+ class ShippingDetails
406
+ include Hanami::Validations
407
+
408
+ attribute :full_name, presence: true
409
+
410
+ attribute :address do
411
+ attribute :street, presence: true
412
+ attribute :city, presence: true
413
+ attribute :country, presence: true
414
+ attribute :postal_code, presence: true, format: /.../
415
+ end
416
+ end
417
+
418
+ validator = ShippingDetails.new
419
+ validator.valid? # => false
420
+ ```
421
+
422
+ Bulk operations on errors are guaranteed by `#each`.
423
+ This method yields a **flattened collection of errors**.
424
+
425
+ ```ruby
426
+ validator.errors.each do |error|
427
+ error.name
428
+ # => on the first iteration it returns "full_name"
429
+ # => the second time it returns "address.street" and so on..
430
+ end
431
+ ```
432
+
433
+ Errors for a specific attribute can be accessed via `#for`.
434
+
435
+ ```ruby
436
+ error = validator.errors.for('full_name').first
437
+ error.name # => "full_name"
438
+ error.attribute_name # => "full_name"
439
+
440
+ error = validator.errors.for('address.street').first
441
+ error.name # => "address.street"
442
+ error.attribute_name # => "street"
443
+ ```
444
+
445
+ ### Composable validations
446
+
447
+ Validations can be reused via composition:
448
+
449
+ ```ruby
450
+ require 'hanami/validations'
451
+
452
+ module NameValidations
453
+ include Hanami::Validations
454
+
455
+ attribute :name, presence: true
456
+ end
30
457
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
458
+ module EmailValidations
459
+ include Hanami::Validations
460
+
461
+ attribute :email, presence: true, format: /.../
462
+ end
463
+
464
+ module PasswordValidations
465
+ include Hanami::Validations
466
+
467
+ # We validate only the presence here
468
+ attribute :password, presence: true
469
+ end
470
+
471
+ module CommonValidations
472
+ include EmailValidations
473
+ include PasswordValidations
474
+ end
475
+
476
+ # A valid signup requires:
477
+ # * name (presence)
478
+ # * email (presence and format)
479
+ # * password (presence and confirmation)
480
+ class Signup
481
+ include NameValidations
482
+ include CommonValidations
483
+
484
+ # We decorate PasswordValidations behavior, by requiring the confirmation too.
485
+ # This additional validation is active only in this case.
486
+ attribute :password, confirmation: true
487
+ end
488
+
489
+ # A valid signin requires:
490
+ # * email (presence)
491
+ # * password (presence)
492
+ class Signin
493
+ include CommonValidations
494
+ end
495
+
496
+ # A valid "forgot password" requires:
497
+ # * email (presence)
498
+ class ForgotPassword
499
+ include EmailValidations
500
+ end
501
+ ```
502
+
503
+ ### Complete example
504
+
505
+ ```ruby
506
+ require 'hanami/validations'
507
+
508
+ class Signup
509
+ include Hanami::Validations
510
+
511
+ attribute :first_name, presence: true
512
+ attribute :last_name, presence: true
513
+ attribute :email, presence: true, format: /\A(.*)@(.*)\.(.*)\z/
514
+ attribute :password, presence: true, confirmation: true, size: 8..64
515
+ end
516
+ ```
517
+
518
+ ### Errors
519
+
520
+ When you invoke `#valid?`, validation errors are available at `#errors`.
521
+ It's a set of errors grouped by attribute. Each error contains the name of the
522
+ invalid attribute, the failed validation, the expected value, and the current one.
523
+
524
+ ```ruby
525
+ require 'hanami/validations'
526
+
527
+ class Signup
528
+ include Hanami::Validations
529
+
530
+ attribute :email, presence: true, format: /\A(.*)@(.*)\.(.*)\z/
531
+ attribute :age, size: 18..99
532
+ end
533
+
534
+ signup = Signup.new(email: 'user@example.org')
535
+ signup.valid? # => true
536
+
537
+ signup = Signup.new(email: '', age: 17)
538
+ signup.valid? # => false
539
+
540
+ signup.errors
541
+ # => #<Hanami::Validations::Errors:0x007fe00ced9b78
542
+ # @errors={
543
+ # :email=>[
544
+ # #<Hanami::Validations::Error:0x007fe00cee3290 @attribute=:email, @validation=:presence, @expected=true, @actual="">,
545
+ # #<Hanami::Validations::Error:0x007fe00cee31f0 @attribute=:email, @validation=:format, @expected=/\A(.*)@(.*)\.(.*)\z/, @actual="">
546
+ # ],
547
+ # :age=>[
548
+ # #<Hanami::Validations::Error:0x007fe00cee30d8 @attribute=:age, @validation=:size, @expected=18..99, @actual=17>
549
+ # ]
550
+ # }>
551
+ ```
552
+
553
+ ### Hanami::Entity
554
+
555
+ Integration with [`Hanami::Entity`](https://github.com/hanami/model) is straight forward.
556
+
557
+ ```ruby
558
+ require 'hanami/model'
559
+ require 'hanami/validations'
560
+
561
+ class Product
562
+ include Hanami::Entity
563
+ include Hanami::Validations
564
+
565
+ attribute :name, type: String, presence: true
566
+ attribute :price, type: Integer, presence: true
567
+ end
568
+
569
+ product = Product.new(name: 'Book', price: '100')
570
+ product.valid? # => true
571
+
572
+ product.name # => "Book"
573
+ product.price # => 100
574
+ ```
32
575
 
33
576
  ## Contributing
34
577
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/hanami-validations.
578
+ 1. Fork it ( https://github.com/hanami/hanami-validations/fork )
579
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
580
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
581
+ 4. Push to the branch (`git push origin my-new-feature`)
582
+ 5. Create a new Pull Request
583
+
584
+ ## Copyright
585
+
586
+ Copyright © 2014-2016 Luca Guidi – Released under MIT License
36
587
 
588
+ This project was formerly known as Lotus (`lotus-validations`).