veto 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +561 -0
- data/Rakefile +1 -0
- data/lib/veto/attribute_validator_factory.rb +32 -0
- data/lib/veto/builder.rb +65 -0
- data/lib/veto/conditions.rb +23 -0
- data/lib/veto/conditions_evaluator.rb +30 -0
- data/lib/veto/configuration.rb +42 -0
- data/lib/veto/errors.rb +35 -0
- data/lib/veto/exceptions.rb +5 -0
- data/lib/veto/model.rb +37 -0
- data/lib/veto/validator.rb +150 -0
- data/lib/veto/validators/abstract_validator.rb +15 -0
- data/lib/veto/validators/attribute_validator.rb +22 -0
- data/lib/veto/validators/custom_method_validator.rb +19 -0
- data/lib/veto/validators/exact_length_validator.rb +15 -0
- data/lib/veto/validators/format_validator.rb +15 -0
- data/lib/veto/validators/inclusion_validator.rb +16 -0
- data/lib/veto/validators/integer_validator.rb +17 -0
- data/lib/veto/validators/length_range_validator.rb +16 -0
- data/lib/veto/validators/max_length_validator.rb +15 -0
- data/lib/veto/validators/min_length_validator.rb +15 -0
- data/lib/veto/validators/not_null_validator.rb +14 -0
- data/lib/veto/validators/numeric_validator.rb +17 -0
- data/lib/veto/validators/presence_validator.rb +15 -0
- data/lib/veto/version.rb +3 -0
- data/lib/veto.rb +53 -0
- data/spec/attribute_validator_factory_spec.rb +72 -0
- data/spec/builder_spec.rb +38 -0
- data/spec/conditions_evaluator_spec.rb +90 -0
- data/spec/conditions_spec.rb +16 -0
- data/spec/configuration/message_spec.rb +30 -0
- data/spec/configuration_spec.rb +6 -0
- data/spec/errors_spec.rb +22 -0
- data/spec/model_spec.rb +67 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/system/validator_spec.rb +380 -0
- data/spec/validator_spec.rb +119 -0
- data/spec/validators/exact_length_validator_spec.rb +37 -0
- data/spec/validators/format_validator_spec.rb +32 -0
- data/spec/validators/inclusion_validator_spec.rb +45 -0
- data/spec/validators/integer_validator_spec.rb +42 -0
- data/spec/validators/length_range_validator_spec.rb +55 -0
- data/spec/validators/max_length_validator_spec.rb +32 -0
- data/spec/validators/min_length_validator_spec.rb +32 -0
- data/spec/validators/not_null_validator_spec.rb +27 -0
- data/spec/validators/numeric_validator_spec.rb +42 -0
- data/spec/validators/presence_validator_spec.rb +47 -0
- data/spec/veto_spec.rb +24 -0
- data/veto.gemspec +24 -0
- 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
data/Gemfile
ADDED
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
|