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
data/lib/veto/builder.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'veto/conditions'
|
2
|
+
require 'veto/attribute_validator_factory'
|
3
|
+
require 'veto/validators/custom_method_validator'
|
4
|
+
|
5
|
+
module Veto
|
6
|
+
class Builder
|
7
|
+
attr_reader :context, :conditions_context
|
8
|
+
|
9
|
+
def initialize context, conditions_context={}, &block
|
10
|
+
@context = context
|
11
|
+
@conditions_context = conditions_context
|
12
|
+
instance_eval(&block) if block_given?
|
13
|
+
end
|
14
|
+
|
15
|
+
def with_options conditions={}, &block
|
16
|
+
mc = ::Veto::Conditions.merge(conditions_context, conditions)
|
17
|
+
::Veto::Builder.new(context, mc, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def validates attribute, options={}
|
21
|
+
a = attribute
|
22
|
+
c = ::Veto::Conditions.select(options)
|
23
|
+
mc = ::Veto::Conditions.merge(conditions_context, c)
|
24
|
+
o = ::Veto::Conditions.reject(options)
|
25
|
+
vs = o.map do |t, vopts|
|
26
|
+
vo = case vopts
|
27
|
+
when TrueClass
|
28
|
+
{}
|
29
|
+
when Hash
|
30
|
+
vopts
|
31
|
+
when Range, Array
|
32
|
+
{ :in => vopts }
|
33
|
+
else
|
34
|
+
{ :with => vopts }
|
35
|
+
end
|
36
|
+
|
37
|
+
vc = ::Veto::Conditions.select(vo)
|
38
|
+
mvc = ::Veto::Conditions.merge(mc, vc)
|
39
|
+
mvo = vo.merge(mvc)
|
40
|
+
::Veto::AttributeValidatorFactory.new_validator(t, a, mvo)
|
41
|
+
end
|
42
|
+
validate_with vs
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate *method_names
|
46
|
+
if method_names.last.is_a?(Hash)
|
47
|
+
c = method_names.last
|
48
|
+
mns = method_names[0..-2]
|
49
|
+
else
|
50
|
+
c = {}
|
51
|
+
mns = method_names
|
52
|
+
end
|
53
|
+
|
54
|
+
mc = ::Veto::Conditions.merge(conditions_context, c)
|
55
|
+
vs = mns.map do |mn|
|
56
|
+
::Veto::CustomMethodValidator.new(mn, mc)
|
57
|
+
end
|
58
|
+
validate_with vs
|
59
|
+
end
|
60
|
+
|
61
|
+
def validate_with *args
|
62
|
+
context.validate_with *args
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Veto
|
2
|
+
class Conditions
|
3
|
+
CONDITION_KEYS = [:if, :unless].freeze
|
4
|
+
|
5
|
+
def self.reject hash={}
|
6
|
+
hash.reject{|k,v| CONDITION_KEYS.include?(k) }
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.select hash={}
|
10
|
+
hash.select{|k,v| CONDITION_KEYS.include?(k) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.merge dest_hash, source_hash
|
14
|
+
CONDITION_KEYS.inject({}) do |m, k|
|
15
|
+
c = []
|
16
|
+
c << dest_hash[k]
|
17
|
+
c << source_hash[k]
|
18
|
+
m[k] = c.flatten.compact
|
19
|
+
m
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Veto
|
2
|
+
class ConditionsEvaluator
|
3
|
+
def self.truthy? condition, context, entity
|
4
|
+
case condition
|
5
|
+
when String
|
6
|
+
!!entity.instance_eval(condition)
|
7
|
+
when Symbol
|
8
|
+
!!context.send(condition)
|
9
|
+
when Proc
|
10
|
+
!!condition.call(entity)
|
11
|
+
else
|
12
|
+
!!condition
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.truthy_conditions? conditions, context, entity
|
17
|
+
return true if !conditions.key?(:if) && !conditions.key?(:unless)
|
18
|
+
|
19
|
+
[*conditions[:if]].each do |condition|
|
20
|
+
return false unless truthy?(condition, context, entity)
|
21
|
+
end
|
22
|
+
|
23
|
+
[*conditions[:unless]].each do |condition|
|
24
|
+
return false if truthy?(condition, context, entity)
|
25
|
+
end
|
26
|
+
|
27
|
+
true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Veto
|
2
|
+
class Configuration
|
3
|
+
class Message
|
4
|
+
DEFAULT_MESSAGES = {
|
5
|
+
:exact_length => lambda{|exact| "is not #{exact} characters"},
|
6
|
+
:format => lambda{"is not valid"},
|
7
|
+
:inclusion => lambda{|set| "is not in set: #{set.inspect}"},
|
8
|
+
:integer => lambda{"is not a number"},
|
9
|
+
:length_range => lambda{"is too short or too long"},
|
10
|
+
:max_length => lambda{|max| "is longer than #{max} characters"},
|
11
|
+
:min_length => lambda{|min| "is shorter than #{min} characters"},
|
12
|
+
:not_null => lambda{"is not present"},
|
13
|
+
:numeric => lambda{"is not a number"},
|
14
|
+
:presence => lambda{"is not present"}
|
15
|
+
}
|
16
|
+
|
17
|
+
def get type, *args
|
18
|
+
args.compact.length > 0 ? message(type).call(*args) : message(type).call
|
19
|
+
end
|
20
|
+
|
21
|
+
def set type, proc
|
22
|
+
custom_messages[type] = proc
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def custom_messages
|
28
|
+
@custom_messages ||= {}
|
29
|
+
end
|
30
|
+
|
31
|
+
def message type
|
32
|
+
custom_messages[type] || DEFAULT_MESSAGES.fetch(type)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_reader :message
|
37
|
+
|
38
|
+
def initialize
|
39
|
+
@message = Message.new
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/veto/errors.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Veto
|
2
|
+
class Errors < ::Hash
|
3
|
+
def add atr, msg, *msg_opts
|
4
|
+
fetch(atr){self[atr] = []} << msg_lookup(msg, *msg_opts)
|
5
|
+
end
|
6
|
+
|
7
|
+
def count
|
8
|
+
values.inject(0){|m, v| m + v.length}
|
9
|
+
end
|
10
|
+
|
11
|
+
def empty?
|
12
|
+
count == 0
|
13
|
+
end
|
14
|
+
|
15
|
+
def full_messages
|
16
|
+
inject([]) do |m, kv|
|
17
|
+
atr, errors = *kv
|
18
|
+
errors.each {|e| m << "#{atr} #{e}"}
|
19
|
+
m
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def on(atr)
|
24
|
+
if v = fetch(atr, nil) and !v.empty?
|
25
|
+
v
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def msg_lookup msg, *msg_opts
|
32
|
+
msg.is_a?(Symbol) ? ::Veto.configuration.message.get(msg, *msg_opts) : msg
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/veto/model.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'veto/exceptions'
|
2
|
+
|
3
|
+
module Veto
|
4
|
+
module Model
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def validates_with veto_validator
|
11
|
+
@validator = veto_validator
|
12
|
+
end
|
13
|
+
|
14
|
+
def validator
|
15
|
+
@validator || raise(::Veto::ValidatorNotAssigned, 'validator not assigned')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid?
|
20
|
+
validator.valid?
|
21
|
+
end
|
22
|
+
|
23
|
+
def validate!
|
24
|
+
validator.validate!
|
25
|
+
end
|
26
|
+
|
27
|
+
def errors
|
28
|
+
validator.errors
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def validator
|
34
|
+
@validator ||= self.class.validator.new(self)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'veto/errors'
|
2
|
+
require 'veto/exceptions'
|
3
|
+
require 'veto/builder'
|
4
|
+
|
5
|
+
module Veto
|
6
|
+
module Validator
|
7
|
+
def self.included(base)
|
8
|
+
base.extend ClassMethods
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def with_options *args, &block
|
13
|
+
builder.with_options(*args, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def validates *args
|
17
|
+
builder.validates(*args)
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate *args
|
21
|
+
builder.validate(*args)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Used to add a validator, or set of validators, to the
|
25
|
+
# validators list. Generally used by the `validates` and `validate`
|
26
|
+
# methods internally.
|
27
|
+
#
|
28
|
+
# @example
|
29
|
+
# PersonValidator.validates_with PresenceValidator.new(:first_name)
|
30
|
+
# # OR
|
31
|
+
# PersonValidator.validates_with PresenceValidator.new(:first_name), IntegerValidator.new(:age)
|
32
|
+
#
|
33
|
+
# @param validator_set [Array] A single, or list, of validator instances
|
34
|
+
def validate_with *validator_set
|
35
|
+
validators.concat validator_set.flatten
|
36
|
+
end
|
37
|
+
|
38
|
+
# Memoizes a flat list of internal validator instances that
|
39
|
+
# will perform validations on the assigned entity.
|
40
|
+
#
|
41
|
+
# @example
|
42
|
+
# PersonValidator.validators # => [
|
43
|
+
# <Veto::FormatValidator:0xXXXXXX @attribute=#<Mock:0xXXXXXX>, @options=#<Mock:0xXXXXXX>>,
|
44
|
+
# <Veto::PresenceValidator:0xXXXXXX @attribute=#<Mock:0xXXXXXX>, @options=#<Mock:0xXXXXXX>>,
|
45
|
+
# <Veto::ExactLengthValidator:0xXXXXXX @attribute=#<Mock:0xXXXXXX>, @options=#<Mock:0xXXXXXX>>]
|
46
|
+
#
|
47
|
+
# @return [Array]
|
48
|
+
def validators
|
49
|
+
@validators ||= []
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns boolean value representing the validaty of the entity
|
53
|
+
#
|
54
|
+
# @param entity [Object] the entity instance to validate.
|
55
|
+
#
|
56
|
+
# @return [Boolean]
|
57
|
+
def valid? entity
|
58
|
+
new(entity).valid?
|
59
|
+
end
|
60
|
+
|
61
|
+
# Raises exception if entity is invalid
|
62
|
+
#
|
63
|
+
# @example
|
64
|
+
# person = Person.new
|
65
|
+
# PersonValidator.validate!(person) # => Veto::InvalidEntity, ["first name is not present", "..."]
|
66
|
+
#
|
67
|
+
# @param entity [Object] the entity instance to be validated.
|
68
|
+
# @raise [Veto::InvalidEntity] if the entity is invalid
|
69
|
+
def validate! entity
|
70
|
+
new(entity).validate!
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def builder
|
76
|
+
@builder ||= ::Veto::Builder.new(self)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Initializes validator
|
81
|
+
#
|
82
|
+
# @param entity [Object] the entity instance to validate.
|
83
|
+
def initialize entity
|
84
|
+
@entity = entity
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns validating entity instance
|
88
|
+
# @return [Object]
|
89
|
+
def entity
|
90
|
+
@entity
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns errors object
|
94
|
+
#
|
95
|
+
# @return [Veto::Errors]
|
96
|
+
def errors
|
97
|
+
@errors ||= ::Veto::Errors.new
|
98
|
+
end
|
99
|
+
|
100
|
+
# Sets errors to nil.
|
101
|
+
def clear_errors
|
102
|
+
@errors = nil
|
103
|
+
end
|
104
|
+
|
105
|
+
# Returns boolean value representing the validaty of the entity
|
106
|
+
#
|
107
|
+
# @return [Boolean]
|
108
|
+
def valid?
|
109
|
+
execute
|
110
|
+
errors.empty?
|
111
|
+
end
|
112
|
+
|
113
|
+
# Raises exception if entity is invalid
|
114
|
+
#
|
115
|
+
# @example
|
116
|
+
# person = Person.new
|
117
|
+
# validator = PersonValidator.new(person)
|
118
|
+
# validator.validate! # => Veto::InvalidEntity, ["first name is not present", "..."]
|
119
|
+
#
|
120
|
+
# @raise [Veto::InvalidEntity] if the entity is invalid
|
121
|
+
def validate!
|
122
|
+
raise(::Veto::InvalidEntity, errors.full_messages) unless valid?
|
123
|
+
end
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
# Executes validation on the entity
|
128
|
+
def execute
|
129
|
+
clear_errors
|
130
|
+
run_validators
|
131
|
+
populate_entity_errors
|
132
|
+
end
|
133
|
+
|
134
|
+
# Runs each of the classes configured validators, passing the
|
135
|
+
# validator instance, entity, and errors object as arguments.
|
136
|
+
# Each validator will inspect the entity, run validations, and
|
137
|
+
# update the errors object according the the validation rules.
|
138
|
+
def run_validators
|
139
|
+
self.class.validators.each { |validator| validator.execute(self, entity, errors) }
|
140
|
+
end
|
141
|
+
|
142
|
+
# If the entity being validated has an errors accessor defined,
|
143
|
+
# assign the errors object to the entity.
|
144
|
+
def populate_entity_errors
|
145
|
+
if entity.respond_to?(:errors=)
|
146
|
+
entity.errors = errors
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'veto/conditions_evaluator'
|
2
|
+
|
3
|
+
module Veto
|
4
|
+
class AbstractValidator
|
5
|
+
def execute(context, entity, errors)
|
6
|
+
raise NotImplementedError
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def truthy_conditions?(conditions, context, entity)
|
12
|
+
ConditionsEvaluator.truthy_conditions?(conditions, context, entity)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'veto/validators/abstract_validator'
|
2
|
+
|
3
|
+
module Veto
|
4
|
+
class AttributeValidator < AbstractValidator
|
5
|
+
def initialize attribute, options={}
|
6
|
+
@attribute = attribute
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def execute context, entity, errors
|
11
|
+
if truthy_conditions?(@options, context, entity)
|
12
|
+
value = entity.public_send(@attribute)
|
13
|
+
validate(entity, @attribute, value, errors, @options)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def validate entity, attribute, value, errors, options={}
|
18
|
+
raise NotImplementedError
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'veto/validators/abstract_validator'
|
2
|
+
|
3
|
+
module Veto
|
4
|
+
class CustomMethodValidator < AbstractValidator
|
5
|
+
|
6
|
+
attr_reader :method_name, :conditions
|
7
|
+
|
8
|
+
def initialize method_name, conditions
|
9
|
+
@method_name = method_name
|
10
|
+
@conditions = conditions
|
11
|
+
end
|
12
|
+
|
13
|
+
def execute context, entity, errors
|
14
|
+
if truthy_conditions?(@conditions, context, entity)
|
15
|
+
context.send(method_name)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'veto/validators/attribute_validator'
|
2
|
+
|
3
|
+
module Veto
|
4
|
+
class ExactLengthValidator < AttributeValidator
|
5
|
+
def validate entity, attribute, value, errors, options={}
|
6
|
+
exact = options.fetch(:with)
|
7
|
+
message = options.fetch(:message, :exact_length)
|
8
|
+
on = options.fetch(:on, attribute)
|
9
|
+
|
10
|
+
if value.nil? || value.length != exact
|
11
|
+
errors.add(on, message, exact)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'veto/validators/attribute_validator'
|
2
|
+
|
3
|
+
module Veto
|
4
|
+
class FormatValidator < AttributeValidator
|
5
|
+
def validate entity, attribute, value, errors, options={}
|
6
|
+
pattern = options.fetch(:with)
|
7
|
+
message = options.fetch(:message, :format)
|
8
|
+
on = options.fetch(:on, attribute)
|
9
|
+
|
10
|
+
unless value.to_s =~ pattern
|
11
|
+
errors.add(on, message)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'veto/validators/attribute_validator'
|
2
|
+
|
3
|
+
module Veto
|
4
|
+
class InclusionValidator < AttributeValidator
|
5
|
+
def validate entity, attribute, value, errors, options={}
|
6
|
+
set = options.fetch(:in)
|
7
|
+
inclusion_method = set.respond_to?(:cover?) ? :cover? : :include?
|
8
|
+
message = options.fetch(:message, :inclusion)
|
9
|
+
on = options.fetch(:on, attribute)
|
10
|
+
|
11
|
+
unless set.send(inclusion_method, value)
|
12
|
+
errors.add(on, message, set)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'veto/validators/attribute_validator'
|
2
|
+
|
3
|
+
module Veto
|
4
|
+
class IntegerValidator < AttributeValidator
|
5
|
+
def validate entity, attribute, value, errors, options={}
|
6
|
+
message = options.fetch(:message, :integer)
|
7
|
+
on = options.fetch(:on, attribute)
|
8
|
+
|
9
|
+
begin
|
10
|
+
Kernel.Integer(value.to_s)
|
11
|
+
nil
|
12
|
+
rescue
|
13
|
+
errors.add(on, message)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'veto/validators/attribute_validator'
|
2
|
+
|
3
|
+
module Veto
|
4
|
+
class LengthRangeValidator < AttributeValidator
|
5
|
+
def validate entity, attribute, value, errors, options={}
|
6
|
+
range = options.fetch(:in)
|
7
|
+
inclusion_method = range.respond_to?(:cover?) ? :cover? : :include?
|
8
|
+
message = options.fetch(:message, :length_range)
|
9
|
+
on = options.fetch(:on, attribute)
|
10
|
+
|
11
|
+
if value.nil? || !range.send(inclusion_method, value.length)
|
12
|
+
errors.add(on, message)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'veto/validators/attribute_validator'
|
2
|
+
|
3
|
+
module Veto
|
4
|
+
class MaxLengthValidator < AttributeValidator
|
5
|
+
def validate entity, attribute, value, errors, options={}
|
6
|
+
max = options.fetch(:with)
|
7
|
+
message = options.fetch(:message, :max_length)
|
8
|
+
on = options.fetch(:on, attribute)
|
9
|
+
|
10
|
+
if value.nil? || value.length > max
|
11
|
+
errors.add(on, message, max)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'veto/validators/attribute_validator'
|
2
|
+
|
3
|
+
module Veto
|
4
|
+
class MinLengthValidator < AttributeValidator
|
5
|
+
def validate entity, attribute, value, errors, options={}
|
6
|
+
min = options.fetch(:with)
|
7
|
+
message = options.fetch(:message, :min_length)
|
8
|
+
on = options.fetch(:on, attribute)
|
9
|
+
|
10
|
+
if value.nil? || value.length < min
|
11
|
+
errors.add(on, message, min)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'veto/validators/attribute_validator'
|
2
|
+
|
3
|
+
module Veto
|
4
|
+
class NotNullValidator < AttributeValidator
|
5
|
+
def validate entity, attribute, value, errors, options={}
|
6
|
+
message = options.fetch(:message, :not_null)
|
7
|
+
on = options.fetch(:on, attribute)
|
8
|
+
|
9
|
+
if value.nil?
|
10
|
+
errors.add(on, message)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'veto/validators/attribute_validator'
|
2
|
+
|
3
|
+
module Veto
|
4
|
+
class NumericValidator < AttributeValidator
|
5
|
+
def validate entity, attribute, value, errors, options={}
|
6
|
+
message = options.fetch(:message, :numeric)
|
7
|
+
on = options.fetch(:on, attribute)
|
8
|
+
|
9
|
+
begin
|
10
|
+
Kernel.Float(value.to_s)
|
11
|
+
nil
|
12
|
+
rescue
|
13
|
+
errors.add(on, message)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'veto/validators/attribute_validator'
|
2
|
+
|
3
|
+
module Veto
|
4
|
+
class PresenceValidator < AttributeValidator
|
5
|
+
def validate entity, attribute, value, errors, options={}
|
6
|
+
msg = options.fetch(:message, :presence)
|
7
|
+
on = options.fetch(:on, attribute)
|
8
|
+
v = value.is_a?(String) ? value.gsub(/\s+/, '') : value
|
9
|
+
|
10
|
+
if v.nil? || v.respond_to?(:empty?) && v.empty?
|
11
|
+
errors.add(on, msg)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/veto/version.rb
ADDED
data/lib/veto.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'veto/version'
|
2
|
+
require 'veto/model'
|
3
|
+
require 'veto/validator'
|
4
|
+
require 'veto/configuration'
|
5
|
+
|
6
|
+
module Veto
|
7
|
+
|
8
|
+
# Provides access to the anonymous validator extension module
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# class PersonValidator
|
12
|
+
# include Veto.validator
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# @return [Module] the object converted into the expected format.
|
16
|
+
def self.validator
|
17
|
+
mod = Module.new
|
18
|
+
mod.define_singleton_method :included do |base|
|
19
|
+
base.send(:include, ::Veto::Validator)
|
20
|
+
end
|
21
|
+
mod
|
22
|
+
end
|
23
|
+
|
24
|
+
# Provides access to the anonymous model extension module
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
# class Person
|
28
|
+
# include Veto.model(PersonValidator)
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# @param validator [Class] the Veto validator class
|
32
|
+
# @return [Module] the object converted into the expected format.
|
33
|
+
def self.model validator
|
34
|
+
mod = Module.new
|
35
|
+
mod.define_singleton_method :included do |base|
|
36
|
+
base.send(:include, ::Veto::Model)
|
37
|
+
base.validates_with validator
|
38
|
+
end
|
39
|
+
mod
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.configure
|
43
|
+
yield(configuration)
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.configuration
|
47
|
+
@configuration ||= ::Veto::Configuration.new
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.configuration= val
|
51
|
+
@configuration = val
|
52
|
+
end
|
53
|
+
end
|