veto 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +561 -0
  6. data/Rakefile +1 -0
  7. data/lib/veto/attribute_validator_factory.rb +32 -0
  8. data/lib/veto/builder.rb +65 -0
  9. data/lib/veto/conditions.rb +23 -0
  10. data/lib/veto/conditions_evaluator.rb +30 -0
  11. data/lib/veto/configuration.rb +42 -0
  12. data/lib/veto/errors.rb +35 -0
  13. data/lib/veto/exceptions.rb +5 -0
  14. data/lib/veto/model.rb +37 -0
  15. data/lib/veto/validator.rb +150 -0
  16. data/lib/veto/validators/abstract_validator.rb +15 -0
  17. data/lib/veto/validators/attribute_validator.rb +22 -0
  18. data/lib/veto/validators/custom_method_validator.rb +19 -0
  19. data/lib/veto/validators/exact_length_validator.rb +15 -0
  20. data/lib/veto/validators/format_validator.rb +15 -0
  21. data/lib/veto/validators/inclusion_validator.rb +16 -0
  22. data/lib/veto/validators/integer_validator.rb +17 -0
  23. data/lib/veto/validators/length_range_validator.rb +16 -0
  24. data/lib/veto/validators/max_length_validator.rb +15 -0
  25. data/lib/veto/validators/min_length_validator.rb +15 -0
  26. data/lib/veto/validators/not_null_validator.rb +14 -0
  27. data/lib/veto/validators/numeric_validator.rb +17 -0
  28. data/lib/veto/validators/presence_validator.rb +15 -0
  29. data/lib/veto/version.rb +3 -0
  30. data/lib/veto.rb +53 -0
  31. data/spec/attribute_validator_factory_spec.rb +72 -0
  32. data/spec/builder_spec.rb +38 -0
  33. data/spec/conditions_evaluator_spec.rb +90 -0
  34. data/spec/conditions_spec.rb +16 -0
  35. data/spec/configuration/message_spec.rb +30 -0
  36. data/spec/configuration_spec.rb +6 -0
  37. data/spec/errors_spec.rb +22 -0
  38. data/spec/model_spec.rb +67 -0
  39. data/spec/spec_helper.rb +6 -0
  40. data/spec/system/validator_spec.rb +380 -0
  41. data/spec/validator_spec.rb +119 -0
  42. data/spec/validators/exact_length_validator_spec.rb +37 -0
  43. data/spec/validators/format_validator_spec.rb +32 -0
  44. data/spec/validators/inclusion_validator_spec.rb +45 -0
  45. data/spec/validators/integer_validator_spec.rb +42 -0
  46. data/spec/validators/length_range_validator_spec.rb +55 -0
  47. data/spec/validators/max_length_validator_spec.rb +32 -0
  48. data/spec/validators/min_length_validator_spec.rb +32 -0
  49. data/spec/validators/not_null_validator_spec.rb +27 -0
  50. data/spec/validators/numeric_validator_spec.rb +42 -0
  51. data/spec/validators/presence_validator_spec.rb +47 -0
  52. data/spec/veto_spec.rb +24 -0
  53. data/veto.gemspec +24 -0
  54. metadata +161 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 59d40a9d79ebae32300dc900d29dcca8bc1d986f
4
+ data.tar.gz: df451e8e91f2b5e398601746c3a8d75114387600
5
+ SHA512:
6
+ metadata.gz: 8e694548ab799c48438c5cc9e5bc14e7d6f4dd59bc9cf35ade6d98aa083871c1b6bfc23b3845b980c163855084081bcbf1d7cebafc38e830a04cfe88c4d180ca
7
+ data.tar.gz: eb2cd741326cc301bca7f586c95ccb5f170fc55d9f25f5ef616cfb1ee550eeebc998d03341039bb669c0cf527ee5c423c81a53992de1633b9fb84717967060b4
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Guardfile
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in veto.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Erik Lott
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 ADDED
@@ -0,0 +1,561 @@
1
+ # Veto
2
+
3
+ Veto provides lightweight validation for plain old ruby objects, using a familiar DSL.
4
+
5
+ Tested on the following Rubies: MRI 2.0.0.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```
12
+ gem 'veto'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ ```
18
+ $ bundle
19
+ ```
20
+
21
+ Or install it yourself as:
22
+
23
+ ```
24
+ $ gem install veto
25
+ ```
26
+ ## Usage
27
+
28
+ ```ruby
29
+ # Create a validator
30
+ class PersonValidator
31
+ include Veto.validator
32
+
33
+ validate :name, :presence => true
34
+ validate :age, :inclusion => 0..100
35
+ end
36
+
37
+ # Create an entity
38
+ class Person
39
+ attr_reader :name, :age, :errors
40
+ end
41
+
42
+ person = Person.new
43
+
44
+ # Validation using class methods
45
+
46
+ PersonValidator.valid?(person) # => false
47
+ PersonValidator.validate!(person) # => # => Veto::InvalidEntity, ["name is not present", "..."]
48
+
49
+ # Validation using validator instance
50
+
51
+ validator = PersonValidator.new(person)
52
+ validator.valid? # => false
53
+ validator.validate! # => # => Veto::InvalidEntity, ["name is not present", "..."]
54
+ validator.errors.full_messages # => ["first name is not present", "..."]
55
+
56
+ # If entity has errors attr_accessor, errors will be passed to the entity
57
+
58
+ person.errors # => nil
59
+ PersonValidator.valid?(person) # => false
60
+ person.errors.full_messages # => ["first name is not present", "..."]
61
+ ```
62
+
63
+ ### Class Method Usage
64
+
65
+ The simplest way to validate an entity is to pass it directly to one of the validator's class methods.
66
+
67
+ #### valid?
68
+
69
+ Validate an entity by passing it to the `valid?` method.
70
+
71
+ ```ruby
72
+ person = Person.new
73
+ PersonValidator.valid?(person) # => false
74
+ ```
75
+
76
+ #### validate!
77
+
78
+ For strict validations, pass the entity to the `validate!` method instead. This method will raise an exception if the validation fails.
79
+
80
+ ```ruby
81
+ person = Person.new
82
+ PersonValidator.validate!(person) # => Veto::InvalidEntity, ["first name is not present", "..."]
83
+ ```
84
+
85
+ ### Instance Method Usage
86
+
87
+ Using a validator instance is also simple, and has some advantages in regards to validation errors (more below). The validation methods available on a validator instance are the same as the class methods.
88
+
89
+ #### initialization
90
+
91
+ When creating a validator instance, the entity you wish to be validated needs to be passed as an argument to the `new` method.
92
+
93
+ ```ruby
94
+ person = Person.new
95
+ validator = PersonValidator.new(person)
96
+ ```
97
+ #### valid?
98
+
99
+ Calling the `valid?` method on a validator instance will return a boolean response, although the method does not receive arguments.
100
+
101
+ ```ruby
102
+ person = Person.new
103
+ validator = PersonValidator.new(person)
104
+ validator.valid? # => false
105
+ ```
106
+
107
+ #### validate!
108
+
109
+ For strict validations…
110
+
111
+ ```ruby
112
+ person = Person.new
113
+ validator = PersonValidator.new(person)
114
+ validator.validate! # => Veto::InvalidEntity, ["first name is not present", "..."]
115
+ ```
116
+
117
+ #### errors
118
+
119
+ The `errors` method will return an errors object. The errors object will contain the error messages generated during the most recent validation.
120
+
121
+ ```ruby
122
+ person = Person.new
123
+ validator = PersonValidator.new(person)
124
+ validator.errors.full_messages # => []
125
+
126
+ validator.valid? # => false
127
+ validator.errors.full_messages # => ["first name is not present", "..."]
128
+ ```
129
+
130
+ ### Errors on Entity
131
+
132
+ Whether you're validating via validator class methods or a validator instance, if the entity being validated has an `errors` attr_accessor defined, the validator will attempt to populate the entity with an errors object each time it is validated.
133
+
134
+ ```ruby
135
+ class Person
136
+ attr_accessor :errors, :first_name, :last_name, ...
137
+ end
138
+
139
+ person = Person.new
140
+ person.errors # => nil
141
+
142
+ PersonValidator.valid?(person) # => false
143
+ person.errors.full_messages # => ["first name is not present", "..."]
144
+ ```
145
+
146
+ ## Validation Helpers
147
+
148
+ ### Presence
149
+ Likely the most used validation helper, the `presence` helper will check that the specified object attribute is not blank. Object attributes that are nil, or respond to `empty?` and return true, are considered blank. All other values will be considered present. This means that `presence` helper is safe to use for boolean attributes, where you need to ensure that the attribute value can be true or false, but not nil.
150
+
151
+ ```ruby
152
+ class PersonValidator
153
+ include Veto.validator
154
+
155
+ validates :first_name, :presence => true
156
+ end
157
+ ```
158
+
159
+ ### Not Null
160
+ Similar to the `presence` helper, the `not_null` helper will strictly check that the specified attribute is not null/nil. Any attribute where `nil?` returns true is considered null. Other values, including blank strings and empty arrays, are all considered not-null and will pass.
161
+
162
+ ```ruby
163
+ class PersonValidator
164
+ include Veto.validator
165
+
166
+ validates :first_name, :not_null => true
167
+ end
168
+ ```
169
+
170
+ ### Format
171
+ The `format` helper ensures that the string value of an attribute matches the specified regular expression. It's useful for ensuring that email addresses, URLs, UPC codes, ISBN codes, and the like, are in a specific format. It can also be used to check that only certain characters are used in the string.
172
+
173
+ ```ruby
174
+ class PersonValidator
175
+ include Veto.validator
176
+
177
+ validates :email, :format => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
178
+
179
+ # OR
180
+
181
+ validates :email, :format => { :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i }
182
+
183
+ end
184
+ ```
185
+
186
+ ### Inclusion
187
+ This helper ensures that an attribute is included in a specified set, or range of values.
188
+
189
+ ```ruby
190
+ class PersonValidator
191
+ include Veto.validator
192
+
193
+ validates :role, :inclusion => [:webmaster, :admin, :user]
194
+
195
+ # OR
196
+
197
+ validates :role, :inclusion => { :in => [:webmaster, :admin, :user] }
198
+ end
199
+ ```
200
+
201
+ ### Integer
202
+ This helper checks that the specified attribute can be a valid integer. For example, the values `123` and `'123'` will both pass, but `123.4` and `'123.4'` will both fail.
203
+
204
+ ```ruby
205
+ class PersonValidator
206
+ include Veto.validator
207
+
208
+ validates :age, :integer => true
209
+ end
210
+ ```
211
+
212
+ ### Numeric
213
+ This helper checks that the specified attribute can be a valid float. For example, the values `123.4` and `'123.4'` will both pass.
214
+
215
+ ```ruby
216
+ class PersonValidator
217
+ include Veto.validator
218
+
219
+ validates :height, :numeric => true
220
+ end
221
+ ```
222
+
223
+ ### Exact Length
224
+ This helper checks that an attribute is an exact length in characters.
225
+
226
+ ```ruby
227
+ class BookValidator
228
+ include Veto.validator
229
+
230
+ validates :isbn, :exact_length => 17
231
+
232
+ # OR
233
+
234
+ validates :isbn, :exact_length => { :with => 17 }
235
+ end
236
+ ```
237
+
238
+ ### Max Length
239
+ This helper checks that an attribute does not exceed a given maximum character length.
240
+
241
+ ```ruby
242
+ class PersonValidator
243
+ include Veto.validator
244
+
245
+ validates :first_name, :max_length => 10
246
+
247
+ # OR
248
+
249
+ validates :first_name, :max_length => { :with => 10 }
250
+ end
251
+ ```
252
+
253
+ ### Min Length
254
+ This helper checks that an attribute is longer than a given minimum character length.
255
+
256
+ ```ruby
257
+ class PersonValidator
258
+ include Veto.validator
259
+
260
+ validates :first_name, :min_length => 3
261
+
262
+ # OR
263
+
264
+ validates :first_name, :min_length => { :with => 3 }
265
+ end
266
+ ```
267
+
268
+ ### Length Range
269
+ This helper checks that the length of an attribute falls within a given range, or other object that responds to `include?`
270
+
271
+ ```ruby
272
+ class PersonValidator
273
+ include Veto.validator
274
+
275
+ validates :first_name, :length_range => 3..10
276
+
277
+ # OR
278
+
279
+ validates :first_name, :length_range => { :in => 3..10 }
280
+ end
281
+ ```
282
+
283
+ ## Common Validation Options
284
+ ### message
285
+
286
+ The `:message` option allows you to specify the error message that will be added to the errors object when validation fails.
287
+
288
+ ```ruby
289
+ class PersonValidator
290
+ include Veto.validator
291
+
292
+ validates :first_name, :presence => {:message => "has not been set"}
293
+ end
294
+ ```
295
+
296
+ ### on
297
+
298
+ The `:on` options allows you to specify which attribute name a given validation error should be applied to.
299
+
300
+ ```ruby
301
+ class PersonValidator
302
+ include Veto.validator
303
+
304
+ validates :first_name, :presence => {:on => :last_name}
305
+ end
306
+
307
+ person = Person.new
308
+ PersonValidator.validate!(person) # => Veto::InvalidEntity, ["last_name is not present""]
309
+ ```
310
+
311
+ ## Conditional Validation
312
+
313
+ You may want a validation to run only when a specified condition is satisfied. To accomplish this, you can pass `:if` and `:unless` options to the validators. Passing an `:if` condition to a validator will ensure that the validation is **only** run if the condition returns true. Passing an `:unless` condition to a validator will ensure that the validation is **always** run unless the condition returns true.
314
+
315
+ ### Using a symbol with :if and :unless
316
+
317
+ Passing a symbol to the :if or :unless option will call the corresponding validator method upon validation.
318
+
319
+ ```ruby
320
+ class PersonValidator
321
+ include Veto.validator
322
+
323
+ validates :last_name, :presence => true, :if => :first_name_set?
324
+
325
+ def first_name_set?
326
+ entity.first_name
327
+ end
328
+ end
329
+ ```
330
+
331
+ ### Using a proc with :if and :unless
332
+
333
+ A Proc object passed to an :if or :unless condition will be run during validation. The Proc object will receive the entity being validated as an argument.
334
+
335
+ ```ruby
336
+ class PersonValidator
337
+ include Veto.validator
338
+
339
+ validates :last_name, :presence => true, :unless => Proc.new{|person| person.first_name.nil? }
340
+ end
341
+ ```
342
+
343
+ ### Using a string with :if and :unless
344
+
345
+ A string passed to the :if or :unless option will be evaluated in the context of the entity being validated.
346
+
347
+ ```ruby
348
+ class PersonValidator
349
+ include Veto.validator
350
+
351
+ validates :last_name, :presence => true, :unless => "first_name.nil?"
352
+ end
353
+ ```
354
+
355
+ ### Grouping Conditional Validations
356
+
357
+ To conditionally run a block of validations, nest them inside a `with_options` method.
358
+
359
+ ```ruby
360
+ class PersonValidator
361
+ include Veto.validator
362
+
363
+ with_options :if => :person_is_admin? do
364
+ validates :admin_secret_code. :presence => true
365
+ validates :admin_level, :inclusion => [3,4,5]
366
+ end
367
+
368
+ def person_is_admin?
369
+ entity.is_admin
370
+ end
371
+ end
372
+ ```
373
+
374
+ ### Combining Conditional Statements
375
+
376
+ You can use multiple `:if` and `:unless` statements together simultaneously in an array. The condition will pass only if all `:if` conditionals return true, and no `:unless` statements return true.
377
+
378
+ ```ruby
379
+ class PersonValidator
380
+ include Veto.validator
381
+
382
+ validates :first_name, :presence => true,
383
+ :if => [:person_has_name?, Proc.new{|person| person.is_human?}],
384
+ :unless => ["nameless?", :skip_name_validation?]
385
+ end
386
+ ```
387
+
388
+ ### Conditional Locations
389
+
390
+ Conditional statements can be assigned as an options hash to the `with_options` method, the `validates` method, or an an options hash for an individual validator in the `validates` method.
391
+
392
+ ```ruby
393
+ class PersonValidator
394
+ include Veto.validator
395
+
396
+ with_options :if => :my_condition_1
397
+ validates :first_name. :presence => true, :min_length => 3, :if => :my_condition_2
398
+ validates :last_name, :presence => {:unless => :my_condition_3}, :min_length => 3
399
+ end
400
+ end
401
+ ```
402
+
403
+ ## Custom Validation
404
+
405
+ Veto provides a few ways to create your own validators and validation methods, when your needs are too complex for the built-in validation syntax.
406
+
407
+ ### Custom Methods
408
+
409
+ You can use a method to check the current state of the entity, and add custom error messages to the errors object if the entity is invalid. Register these methods using the `validate` method. Multiple validation methods can be assigned at once, as well as a hash of condition options included as the last method argument.
410
+
411
+ ```ruby
412
+ class PersonValidator
413
+ include Veto.validator
414
+
415
+ validate :supervisor_must_have_supervisor_code, :admins_have_last_names
416
+
417
+ def supervisor_must_have_supervisor_code
418
+ if entity.is_admin? && entity.employees.size > 0 && supervisor_code.nil?
419
+ errors.add(:supervisor_code, "can't be blank")
420
+ end
421
+ end
422
+
423
+ def admins_have_last_names
424
+ if entity.is_admin? && entity.last_name
425
+ errors.add(:last_name, "can't be blank")
426
+ end
427
+ end
428
+ end
429
+ ```
430
+
431
+ ### Custom Attribute Validator
432
+
433
+ Much like the built-in `presence`, `max_length`, and `format` attribute validators, you can create your own custom validator, and refer to it using the `validates` method. Custom attribute validators must extend the Veto::AttributeValidator class, implement a `validate` method which receives 5 arguments: entity, attribute, value, errors, and options.
434
+
435
+ ```ruby
436
+ class PersonValidator
437
+ include Veto.validator
438
+
439
+ class EmailValidator < ::Veto::AttributeValidator
440
+ def validate(entity, attribute, value, errors, options={})
441
+ unless value.to_s =~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
442
+ errors.add(attribute, "is not a valid email address")
443
+ end
444
+ end
445
+ end
446
+
447
+ validates :electronic_address, :email => true
448
+ end
449
+ ```
450
+
451
+ ## Configuration
452
+
453
+ Call the Veto `configure` method to yield the configuration object.
454
+
455
+ ```ruby
456
+ Veto.configure do |c|
457
+ ...
458
+ end
459
+ ```
460
+
461
+ ### Messages
462
+
463
+ The `message` configuration object, allows you to change the default error message produced by each attribute validator. The message must be in the form of a lambda or Proc, and may or may not receive an argument. Use the example below for reference when customizing messages.
464
+
465
+ ```ruby
466
+ Veto.configure do |c|
467
+ c.message.set(:exact_length, lambda{|exact| "is not #{exact} characters"})
468
+ c.message.set(:format, lambda{"is not valid"})
469
+ c.message.set(:inclusion, lambda{|set| "is not in set: #{set.inspect}"})
470
+ c.message.set(:integer, lambda{"is not a number"})
471
+ c.message.set(:length_range, lambda{"is too short or too long"})
472
+ c.message.set(:max_length, lambda{|max| "is longer than #{max} characters"})
473
+ c.message.set(:min_length, lambda{|min| "is shorter than #{min} characters"})
474
+ c.message.set(:not_null, lambda{"is not present"})
475
+ c.message.set(:numeric, lambda{"is not a number"})
476
+ c.message.set(:presence, lambda{"is not present"})
477
+ end
478
+ ```
479
+
480
+ If you would like to change the default message produced by a specified validator, you can do so using through the configuration object.
481
+
482
+ Create a new validator by including the Veto validator module in your class.
483
+
484
+ ```ruby
485
+ class PersonValidator
486
+ include Veto.validator
487
+ end
488
+ ```
489
+
490
+ ## Working With Errors
491
+
492
+ Veto's simple errors object is a subclass of hash, with a few additional methods for inspecting the collection of error messages.
493
+
494
+ #### errors.add
495
+ Adds a method to the errors object.
496
+
497
+ ```ruby
498
+ errors.add(:first_name, "is not present")
499
+ ```
500
+
501
+ #### errors.empty?
502
+ Returns a boolean value representing if the errors object is empty or not.
503
+
504
+ ```ruby
505
+ errors.empty? # => true
506
+ errors.add(:first_name, "is not present")
507
+ errors.empty? # => false
508
+ ```
509
+
510
+ #### errors.count
511
+ Returns the number of errors present in the errors object.
512
+
513
+ ```ruby
514
+ errors.count # => 0
515
+ errors.add(:first_name, "is not present")
516
+ errors.count # => 1
517
+ ```
518
+
519
+ #### errors.on
520
+ Returns a list of error message for a given attribute.
521
+
522
+ ```ruby
523
+ errors.on(:first_name) # => nil
524
+ errors.add(:first_name, "is not present")
525
+ errors.add(:first_name, "is too short")
526
+ errors.on(:first_name) # => ["is not present", "is too short"]
527
+ ```
528
+
529
+ #### errors.full_messages
530
+ Returns a list of full error messages.
531
+
532
+ ```ruby
533
+ errors.add(:first_name, "is not present")
534
+ errors.add(:last_name, "is too short")
535
+ errors.full_messages # => ["first_name is not present", "last_name is too short"]
536
+ ```
537
+
538
+ ## Veto Model
539
+
540
+ If your entities and validators have a strict 1-to-1 relationship (an entity will only ever be validated by a single validator, and a validator will only ever validate a single entity), it might make sense to embed the validator directly inside the entity.
541
+
542
+ The Veto Model extension does exactly this, associating your entity with a specified validator, and adding 3 additional methods to your entity: `valid?`, `validate!`, and `errors`
543
+
544
+ ```ruby
545
+ class Person
546
+ include Veto.model(PersonValidator)
547
+ end
548
+
549
+ person.new
550
+ person.valid? # => false
551
+ person.errors.full_messages # => ["first name is not present", "last name is not present"]
552
+ person.validate! # => Veto::InvalidEntity, ["first name is not present", "..."]
553
+ ```
554
+
555
+ ## Contributing
556
+
557
+ 1. Fork it
558
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
559
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
560
+ 4. Push to the branch (`git push origin my-new-feature`)
561
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,32 @@
1
+ require 'veto/validators/exact_length_validator'
2
+ require 'veto/validators/format_validator'
3
+ require 'veto/validators/inclusion_validator'
4
+ require 'veto/validators/integer_validator'
5
+ require 'veto/validators/length_range_validator'
6
+ require 'veto/validators/max_length_validator'
7
+ require 'veto/validators/min_length_validator'
8
+ require 'veto/validators/not_null_validator'
9
+ require 'veto/validators/numeric_validator'
10
+ require 'veto/validators/presence_validator'
11
+
12
+ module Veto
13
+ class AttributeValidatorFactory
14
+ def self.new_validator type, attribute, options={}
15
+ klass_name = "::Veto::#{camel_case(type.to_s)}Validator"
16
+
17
+ begin
18
+ klass = const_get(klass_name)
19
+ rescue NameError => e
20
+ raise(ArgumentError, "Validator not found: #{klass_name}")
21
+ end
22
+
23
+ klass.new(attribute, options)
24
+ end
25
+
26
+ private
27
+
28
+ def self.camel_case(str)
29
+ str.split('_').map{|w| w.capitalize }.join('')
30
+ end
31
+ end
32
+ end