veto 0.0.1
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 +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
|