validatable 1.1.2 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +30 -1
- data/lib/base.rb +96 -20
- data/lib/child_validation.rb +15 -0
- data/lib/errors.rb +6 -1
- data/lib/validatable.rb +4 -1
- data/lib/validations/validates_confirmation_of.rb +4 -1
- data/lib/validations/validates_numericality_of.rb +13 -0
- data/lib/validations/validates_true_for.rb +13 -0
- data/lib/validations/validation_base.rb +26 -4
- data/rakefile.rb +1 -1
- data/test/functional/validatable_test.rb +129 -0
- data/test/functional/validates_confirmation_of_test.rb +38 -0
- data/test/functional/validates_numericality_of_test.rb +45 -0
- data/test/functional/validates_true_for_test.rb +27 -0
- data/test/unit/validatable_test.rb +1 -9
- data/test/unit/validates_confirmation_of_test.rb +50 -0
- data/test/unit/validates_numericality_of_test.rb +36 -0
- data/test/unit/validates_true_for_test.rb +16 -0
- metadata +11 -3
data/README
CHANGED
@@ -72,8 +72,37 @@ Similar to Rails, Validatable also supports conditional validation.
|
|
72
72
|
validates_format_of :name, :with => /.+/, :if => Proc.new { !name.nil? }
|
73
73
|
end
|
74
74
|
Person.new.valid? #=> true
|
75
|
+
|
76
|
+
Validatable also exposes an after_validate hook method.
|
77
|
+
|
78
|
+
class Person
|
79
|
+
include Validatable
|
80
|
+
validates_presence_of :name
|
81
|
+
attr_accessor :name
|
82
|
+
end
|
83
|
+
|
84
|
+
class ValidatesPresenceOf
|
85
|
+
after_validate do |result, instance, attribute|
|
86
|
+
instance.errors.add("#{attribute} can't be blank") unless result
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
person = Person.new
|
91
|
+
person.valid? #=> false
|
92
|
+
person.errors.on(:name) #=> "name can't be blank"
|
93
|
+
|
94
|
+
The after_validate hook yields the result of the validation being run,
|
95
|
+
the instance the validation was run on, and the attribute that was validate
|
96
|
+
|
97
|
+
In the above example the attribute "name" is appended to the message.
|
75
98
|
|
76
99
|
See the tests for more examples
|
77
100
|
|
78
101
|
== Contributors
|
79
|
-
Rick Bradley (Revision 25)
|
102
|
+
Rick Bradley (Revision 25)
|
103
|
+
|
104
|
+
Zak Tamsen (Revision 29)
|
105
|
+
|
106
|
+
Jason Miller (Revision 31)
|
107
|
+
|
108
|
+
Ali Aghareza (Revision 45)
|
data/lib/base.rb
CHANGED
@@ -18,6 +18,7 @@ module Validatable
|
|
18
18
|
# * level - The level at which the validation should occur
|
19
19
|
# * if - A block that when executed must return true of the validation will not occur
|
20
20
|
# * with - The regular expression used to validate the format
|
21
|
+
# * group - The group that this validation belongs to. A validation can belong to multiple groups
|
21
22
|
def validates_format_of(*args)
|
22
23
|
add_validations(args, ValidatesFormatOf) do |validation, options|
|
23
24
|
validation.with = options[:with]
|
@@ -42,6 +43,7 @@ module Validatable
|
|
42
43
|
# * if - A block that when executed must return true of the validation will not occur
|
43
44
|
# * minimum - The minimum size of the attribute
|
44
45
|
# * maximum - The maximum size of the attribute
|
46
|
+
# * group - The group that this validation belongs to. A validation can belong to multiple groups
|
45
47
|
def validates_length_of(*args)
|
46
48
|
add_validations(args, ValidatesLengthOf) do |validation, options|
|
47
49
|
validation.minimum = options[:minimum]
|
@@ -49,6 +51,26 @@ module Validatable
|
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
54
|
+
# call-seq: validates_numericality_of(*args)
|
55
|
+
#
|
56
|
+
# Validates that the specified attribute is numeric.
|
57
|
+
#
|
58
|
+
# class Person
|
59
|
+
# include Validatable
|
60
|
+
# validates_numericality_of :age
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# Configuration options:
|
64
|
+
#
|
65
|
+
# * message - The message to add to the errors collection when the validation fails
|
66
|
+
# * times - The number of times the validation applies
|
67
|
+
# * level - The level at which the validation should occur
|
68
|
+
# * if - A block that when executed must return true of the validation will not occur
|
69
|
+
# * group - The group that this validation belongs to. A validation can belong to multiple groups
|
70
|
+
def validates_numericality_of(*args)
|
71
|
+
add_validations(args, ValidatesNumericalityOf)
|
72
|
+
end
|
73
|
+
|
52
74
|
# call-seq: validates_acceptance_of(*args)
|
53
75
|
#
|
54
76
|
# Encapsulates the pattern of wanting to validate the acceptance of a terms of service check box (or similar agreement). Example:
|
@@ -65,6 +87,7 @@ module Validatable
|
|
65
87
|
# * times - The number of times the validation applies
|
66
88
|
# * level - The level at which the validation should occur
|
67
89
|
# * if - A block that when executed must return true of the validation will not occur
|
90
|
+
# * group - The group that this validation belongs to. A validation can belong to multiple groups
|
68
91
|
def validates_acceptance_of(*args)
|
69
92
|
add_validations(args, ValidatesAcceptanceOf)
|
70
93
|
end
|
@@ -86,12 +109,20 @@ module Validatable
|
|
86
109
|
#
|
87
110
|
# Configuration options:
|
88
111
|
#
|
112
|
+
# * case_sensitive - Whether or not to apply case-sensitivity on the comparison. Defaults to true.
|
89
113
|
# * message - The message to add to the errors collection when the validation fails
|
90
114
|
# * times - The number of times the validation applies
|
91
115
|
# * level - The level at which the validation should occur
|
92
116
|
# * if - A block that when executed must return true of the validation will not occur
|
117
|
+
# * group - The group that this validation belongs to. A validation can belong to multiple groups
|
93
118
|
def validates_confirmation_of(*args)
|
94
|
-
add_validations(args, ValidatesConfirmationOf)
|
119
|
+
add_validations(args, ValidatesConfirmationOf) do |validation, options|
|
120
|
+
validation.case_sensitive = if options.has_key? :case_sensitive
|
121
|
+
options[:case_sensitive]
|
122
|
+
else
|
123
|
+
true
|
124
|
+
end
|
125
|
+
end
|
95
126
|
end
|
96
127
|
|
97
128
|
# call-seq: validates_presence_of(*args)
|
@@ -111,11 +142,37 @@ module Validatable
|
|
111
142
|
# * times - The number of times the validation applies
|
112
143
|
# * level - The level at which the validation should occur
|
113
144
|
# * if - A block that when executed must return true of the validation will not occur
|
145
|
+
# * group - The group that this validation belongs to. A validation can belong to multiple groups
|
114
146
|
def validates_presence_of(*args)
|
115
147
|
add_validations(args, ValidatesPresenceOf)
|
116
148
|
end
|
117
149
|
|
118
|
-
# call-seq:
|
150
|
+
# call-seq: validates_true_for(*args)
|
151
|
+
#
|
152
|
+
# Validates that the logic evaluates to true
|
153
|
+
#
|
154
|
+
# class Person
|
155
|
+
# include Validatable
|
156
|
+
# validates_true_for :first_name, :logic => lambda { first_name == 'Jamie' }
|
157
|
+
# end
|
158
|
+
#
|
159
|
+
# The logic option is required.
|
160
|
+
#
|
161
|
+
# Configuration options:
|
162
|
+
#
|
163
|
+
# * message - The message to add to the errors collection when the validation fails
|
164
|
+
# * times - The number of times the validation applies
|
165
|
+
# * level - The level at which the validation should occur
|
166
|
+
# * if - A block that when executed must return true of the validation will not occur
|
167
|
+
# * group - The group that this validation belongs to. A validation can belong to multiple groups
|
168
|
+
# * logic - A block that executes to perform the validation
|
169
|
+
def validates_true_for(*args)
|
170
|
+
add_validations(args, ValidatesTrueFor) do |validation, options|
|
171
|
+
validation.logic = options[:logic]
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# call-seq: include_validations_for(attribute_to_validate, options = {})
|
119
176
|
#
|
120
177
|
# Validates the specified attributes.
|
121
178
|
# class Person
|
@@ -126,7 +183,7 @@ module Validatable
|
|
126
183
|
#
|
127
184
|
# class PersonPresenter
|
128
185
|
# include Validatable
|
129
|
-
# include_validations_for :person
|
186
|
+
# include_validations_for :person, :map => { :name => :namen }, :if => lambda { not person.nil? }
|
130
187
|
# attr_accessor :person
|
131
188
|
#
|
132
189
|
# def initialize(person)
|
@@ -136,11 +193,16 @@ module Validatable
|
|
136
193
|
#
|
137
194
|
# presenter = PersonPresenter.new(Person.new)
|
138
195
|
# presenter.valid? #=> false
|
139
|
-
# presenter.errors.on(:
|
196
|
+
# presenter.errors.on(:namen) #=> "can't be blank"
|
140
197
|
#
|
141
198
|
# The person attribute will be validated. If person is invalid the errors will be added to the PersonPresenter errors collection.
|
142
|
-
|
143
|
-
|
199
|
+
#
|
200
|
+
# Configuration options:
|
201
|
+
#
|
202
|
+
# * map - A hash that maps attributes of the child to attributes of the parent.
|
203
|
+
# * if - A block that when executed must return true of the validation will not occur.
|
204
|
+
def include_validations_for(attribute_to_validate, options = {})
|
205
|
+
children_to_validate << ChildValidation.new(attribute_to_validate, options[:map] || {}, options[:if] || lambda { true })
|
144
206
|
end
|
145
207
|
|
146
208
|
def validate(instance) #:nodoc:
|
@@ -155,12 +217,13 @@ module Validatable
|
|
155
217
|
end
|
156
218
|
end
|
157
219
|
|
158
|
-
def validate_children(instance) #:nodoc:
|
159
|
-
self.children_to_validate.each do |
|
160
|
-
|
161
|
-
child.
|
220
|
+
def validate_children(instance, groups) #:nodoc:
|
221
|
+
self.children_to_validate.each do |child_validation|
|
222
|
+
next unless child_validation.should_validate?(instance)
|
223
|
+
child = instance.send child_validation.attribute
|
224
|
+
child.valid?(*groups)
|
162
225
|
child.errors.each do |attribute, message|
|
163
|
-
instance.errors.add(attribute, message)
|
226
|
+
instance.errors.add(child_validation.map[attribute.to_sym] || attribute, message)
|
164
227
|
end
|
165
228
|
end
|
166
229
|
end
|
@@ -191,10 +254,10 @@ module Validatable
|
|
191
254
|
# call-seq: valid?
|
192
255
|
#
|
193
256
|
# Returns true if no errors were added otherwise false.
|
194
|
-
def valid?
|
257
|
+
def valid?(*groups)
|
195
258
|
errors.clear
|
196
|
-
self.class.validate_children(self)
|
197
|
-
self.validate
|
259
|
+
self.class.validate_children(self, groups)
|
260
|
+
self.validate(groups)
|
198
261
|
errors.empty?
|
199
262
|
end
|
200
263
|
|
@@ -206,17 +269,25 @@ module Validatable
|
|
206
269
|
end
|
207
270
|
|
208
271
|
protected
|
209
|
-
def validate #:nodoc:
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
272
|
+
def validate(groups) #:nodoc:
|
273
|
+
validations_for_groups(groups).each do |validation|
|
274
|
+
validation_levels.sort.each do |level|
|
275
|
+
validations_for_level(level).each do |validation|
|
276
|
+
if validation.should_validate?(self)
|
277
|
+
run_validation(validation)
|
278
|
+
end
|
214
279
|
end
|
280
|
+
return unless self.errors.empty?
|
215
281
|
end
|
216
|
-
return unless self.errors.empty?
|
217
282
|
end
|
218
283
|
end
|
219
284
|
|
285
|
+
def run_validation(validation) #:nodoc:
|
286
|
+
validation_result = validation.valid?(self)
|
287
|
+
self.errors.add(validation.attribute, validation.message) unless validation_result
|
288
|
+
validation.run_after_validate(validation_result, self, validation.attribute)
|
289
|
+
end
|
290
|
+
|
220
291
|
def validation_levels #:nodoc:
|
221
292
|
self.validations.collect { |validation| validation.level }.uniq
|
222
293
|
end
|
@@ -225,6 +296,11 @@ module Validatable
|
|
225
296
|
self.validations.select { |validation| validation.level == level }
|
226
297
|
end
|
227
298
|
|
299
|
+
def validations_for_groups(groups) #:nodoc:
|
300
|
+
return self.validations if groups.empty?
|
301
|
+
self.validations.select { |validation| (groups & validation.groups).any? }
|
302
|
+
end
|
303
|
+
|
228
304
|
def validations #:nodoc:
|
229
305
|
@validations ||= self.class.validations.collect { |validation| validation.dup }
|
230
306
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Validatable
|
2
|
+
class ChildValidation #:nodoc:
|
3
|
+
attr_accessor :attribute, :map, :should_validate_proc
|
4
|
+
|
5
|
+
def initialize(attribute, map, should_validate_proc)
|
6
|
+
@attribute = attribute
|
7
|
+
@map = map
|
8
|
+
@should_validate_proc = should_validate_proc
|
9
|
+
end
|
10
|
+
|
11
|
+
def should_validate?(instance)
|
12
|
+
instance.instance_eval &should_validate_proc
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/errors.rb
CHANGED
@@ -2,7 +2,7 @@ module Validatable
|
|
2
2
|
class Errors
|
3
3
|
extend Forwardable
|
4
4
|
|
5
|
-
def_delegators :errors, :
|
5
|
+
def_delegators :errors, :any?, :clear, :each, :each_pair, :empty?, :length, :size
|
6
6
|
|
7
7
|
# call-seq: on(attribute)
|
8
8
|
#
|
@@ -15,6 +15,11 @@ module Validatable
|
|
15
15
|
def add(attribute, message) #:nodoc:
|
16
16
|
errors[attribute.to_sym] = message
|
17
17
|
end
|
18
|
+
|
19
|
+
def merge!(errors) #:nodoc:
|
20
|
+
errors.each_pair{|k, v| add(k,v)}
|
21
|
+
self
|
22
|
+
end
|
18
23
|
|
19
24
|
def errors #:nodoc:
|
20
25
|
@errors ||= {}
|
data/lib/validatable.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
require File.expand_path(File.dirname(__FILE__) + '/errors')
|
3
3
|
require File.expand_path(File.dirname(__FILE__) + '/base')
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + '/child_validation')
|
4
5
|
require File.expand_path(File.dirname(__FILE__) + '/validations/validation_base')
|
5
6
|
require File.expand_path(File.dirname(__FILE__) + '/validations/validates_format_of')
|
6
7
|
require File.expand_path(File.dirname(__FILE__) + '/validations/validates_presence_of')
|
7
8
|
require File.expand_path(File.dirname(__FILE__) + '/validations/validates_acceptance_of')
|
8
9
|
require File.expand_path(File.dirname(__FILE__) + '/validations/validates_confirmation_of')
|
9
|
-
require File.expand_path(File.dirname(__FILE__) + '/validations/validates_length_of')
|
10
|
+
require File.expand_path(File.dirname(__FILE__) + '/validations/validates_length_of')
|
11
|
+
require File.expand_path(File.dirname(__FILE__) + '/validations/validates_true_for')
|
12
|
+
require File.expand_path(File.dirname(__FILE__) + '/validations/validates_numericality_of')
|
@@ -1,7 +1,10 @@
|
|
1
1
|
module Validatable
|
2
2
|
class ValidatesConfirmationOf < ValidationBase #:nodoc:
|
3
|
+
attr_accessor :case_sensitive
|
4
|
+
|
3
5
|
def valid?(instance)
|
4
|
-
instance.send(self.attribute) == instance.send("#{self.attribute}_confirmation".to_sym)
|
6
|
+
return instance.send(self.attribute) == instance.send("#{self.attribute}_confirmation".to_sym) if case_sensitive
|
7
|
+
instance.send(self.attribute).to_s.casecmp(instance.send("#{self.attribute}_confirmation".to_sym).to_s) == 0
|
5
8
|
end
|
6
9
|
|
7
10
|
def message
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Validatable
|
2
2
|
class ValidationBase #:nodoc:
|
3
|
-
attr_accessor :attribute, :message
|
4
|
-
attr_reader :level
|
3
|
+
attr_accessor :attribute, :message, :times
|
4
|
+
attr_reader :level, :groups
|
5
5
|
|
6
6
|
def initialize(attribute, options={})
|
7
7
|
@attribute = attribute
|
@@ -9,6 +9,7 @@ module Validatable
|
|
9
9
|
@conditional = options[:if] || Proc.new { true }
|
10
10
|
@times = options[:times]
|
11
11
|
@level = options[:level] || 1
|
12
|
+
@groups = options[:groups].is_a?(Array) ? options[:groups] : [options[:groups]]
|
12
13
|
end
|
13
14
|
|
14
15
|
def should_validate?(instance)
|
@@ -17,8 +18,29 @@ module Validatable
|
|
17
18
|
|
18
19
|
def validate_this_time?
|
19
20
|
return true if @times.nil?
|
20
|
-
|
21
|
-
|
21
|
+
self.times -= 1
|
22
|
+
self.times >= 0
|
23
|
+
end
|
24
|
+
|
25
|
+
def run_after_validate(result, instance, attribute)
|
26
|
+
self.class.all_after_validations.each do |block|
|
27
|
+
block.call result, instance, attribute
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class << self
|
32
|
+
def after_validate(&block)
|
33
|
+
after_validations << block
|
34
|
+
end
|
35
|
+
|
36
|
+
def after_validations
|
37
|
+
@after_validations ||= []
|
38
|
+
end
|
39
|
+
|
40
|
+
def all_after_validations
|
41
|
+
return after_validations + self.superclass.after_validations if self.superclass.respond_to? :after_validations
|
42
|
+
after_validations
|
43
|
+
end
|
22
44
|
end
|
23
45
|
end
|
24
46
|
end
|
data/rakefile.rb
CHANGED
@@ -29,7 +29,7 @@ Gem::manage_gems
|
|
29
29
|
specification = Gem::Specification.new do |s|
|
30
30
|
s.name = "validatable"
|
31
31
|
s.summary = "Validatable is a library for adding validations."
|
32
|
-
s.version = "1.1
|
32
|
+
s.version = "1.2.1"
|
33
33
|
s.author = 'Jay Fields'
|
34
34
|
s.description = "Validatable is a library for adding validations."
|
35
35
|
s.email = 'validatable-developer@rubyforge.org'
|
@@ -22,6 +22,135 @@ module Functional
|
|
22
22
|
assert_equal "can't be empty", instance.errors.on(:name)
|
23
23
|
end
|
24
24
|
|
25
|
+
test "given a child class with validations, the error is in the parent objects error collection as the mapped attribute" do
|
26
|
+
child_class = Class.new do
|
27
|
+
include Validatable
|
28
|
+
attr_accessor :name, :address
|
29
|
+
validates_presence_of :name
|
30
|
+
end
|
31
|
+
klass = Class.new do
|
32
|
+
include Validatable
|
33
|
+
include_validations_for :child, :map => {:name => :namen}
|
34
|
+
define_method :child do
|
35
|
+
child_class.new
|
36
|
+
end
|
37
|
+
end
|
38
|
+
instance = klass.new
|
39
|
+
instance.valid?
|
40
|
+
assert_equal "can't be empty", instance.errors.on(:namen)
|
41
|
+
end
|
42
|
+
|
43
|
+
test "given a child class with validations, the error is in the parent objects error collection when the 'if' evals to true" do
|
44
|
+
child_class = Class.new do
|
45
|
+
include Validatable
|
46
|
+
attr_accessor :name, :address
|
47
|
+
validates_presence_of :name
|
48
|
+
end
|
49
|
+
klass = Class.new do
|
50
|
+
include Validatable
|
51
|
+
include_validations_for :child, :if => lambda { true }
|
52
|
+
define_method :child do
|
53
|
+
child_class.new
|
54
|
+
end
|
55
|
+
end
|
56
|
+
instance = klass.new
|
57
|
+
instance.valid?
|
58
|
+
assert_equal "can't be empty", instance.errors.on(:name)
|
59
|
+
end
|
60
|
+
|
61
|
+
test "given a child class with validations, the error is not in the parent objects error collection when the if evals to false" do
|
62
|
+
child_class = Class.new do
|
63
|
+
include Validatable
|
64
|
+
attr_accessor :name, :address
|
65
|
+
validates_presence_of :name
|
66
|
+
end
|
67
|
+
klass = Class.new do
|
68
|
+
include Validatable
|
69
|
+
include_validations_for :child, :if => lambda { false }
|
70
|
+
define_method :child do
|
71
|
+
child_class.new
|
72
|
+
end
|
73
|
+
end
|
74
|
+
instance = klass.new
|
75
|
+
assert_equal true, instance.valid?
|
76
|
+
end
|
77
|
+
|
78
|
+
test "nonmatching groups are not used as validations" do
|
79
|
+
klass = Class.new do
|
80
|
+
include Validatable
|
81
|
+
validates_presence_of :name, :groups => :group_one
|
82
|
+
attr_accessor :name
|
83
|
+
end
|
84
|
+
instance = klass.new
|
85
|
+
assert_equal true, instance.valid?(:group_two)
|
86
|
+
end
|
87
|
+
|
88
|
+
test "after validate is called following a validation" do
|
89
|
+
klass = Class.new do
|
90
|
+
include Validatable
|
91
|
+
validates_presence_of :name
|
92
|
+
attr_accessor :name
|
93
|
+
end
|
94
|
+
|
95
|
+
Validatable::ValidationBase.class_eval do
|
96
|
+
after_validate do |result, instance, attribute|
|
97
|
+
instance.errors.add(attribute, instance.errors.on(attribute) + " changed message")
|
98
|
+
end
|
99
|
+
end
|
100
|
+
Validatable::ValidatesPresenceOf.class_eval do
|
101
|
+
after_validate do |result, instance, attribute|
|
102
|
+
instance.errors.add(attribute, instance.errors.on(attribute) + " twice")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
instance = klass.new
|
106
|
+
instance.valid?
|
107
|
+
assert_equal "can't be empty twice changed message", instance.errors.on(:name)
|
108
|
+
Validatable::ValidatesPresenceOf.after_validations.clear
|
109
|
+
Validatable::ValidationBase.after_validations.clear
|
110
|
+
end
|
111
|
+
|
112
|
+
test "matching groups are used as validations when multiple groups are given to valid" do
|
113
|
+
klass = Class.new do
|
114
|
+
include Validatable
|
115
|
+
validates_presence_of :name, :groups => :group_one
|
116
|
+
attr_accessor :name
|
117
|
+
end
|
118
|
+
instance = klass.new
|
119
|
+
assert_equal false, instance.valid?(:group_one)
|
120
|
+
end
|
121
|
+
|
122
|
+
test "matching groups are used as validations when validations are part of multiple groups" do
|
123
|
+
klass = Class.new do
|
124
|
+
include Validatable
|
125
|
+
validates_presence_of :name, :groups => [:group_one, :group_two]
|
126
|
+
attr_accessor :name
|
127
|
+
end
|
128
|
+
instance = klass.new
|
129
|
+
assert_equal false, instance.valid?(:group_one)
|
130
|
+
end
|
131
|
+
|
132
|
+
test "no group given then all validations are used" do
|
133
|
+
klass = Class.new do
|
134
|
+
include Validatable
|
135
|
+
validates_presence_of :name, :groups => :group_one
|
136
|
+
attr_accessor :name
|
137
|
+
end
|
138
|
+
instance = klass.new
|
139
|
+
assert_equal false, instance.valid?
|
140
|
+
end
|
141
|
+
|
142
|
+
test "matching multiple groups for validations" do
|
143
|
+
klass = Class.new do
|
144
|
+
include Validatable
|
145
|
+
validates_presence_of :name, :groups => :group_one
|
146
|
+
validates_presence_of :address, :groups => :group_two
|
147
|
+
attr_accessor :name, :address
|
148
|
+
end
|
149
|
+
instance = klass.new
|
150
|
+
instance.valid?(:group_one, :group_two)
|
151
|
+
assert_equal 2, instance.errors.size
|
152
|
+
end
|
153
|
+
|
25
154
|
expect true do
|
26
155
|
klass = Class.new do
|
27
156
|
include Validatable
|
@@ -14,5 +14,43 @@ module Functional
|
|
14
14
|
instance.valid?
|
15
15
|
assert_equal "doesn't match confirmation", instance.errors.on(:name)
|
16
16
|
end
|
17
|
+
|
18
|
+
test "given matching attributes, when validated, then no error is in the objects error collection" do
|
19
|
+
klass = Class.new do
|
20
|
+
include Validatable
|
21
|
+
attr_accessor :name, :name_confirmation
|
22
|
+
validates_confirmation_of :name
|
23
|
+
end
|
24
|
+
instance = klass.new
|
25
|
+
instance.name = "foo"
|
26
|
+
instance.name_confirmation = "foo"
|
27
|
+
assert_equal true, instance.valid?
|
28
|
+
end
|
29
|
+
|
30
|
+
test "given matching attributes of different case, when validated with case sensitive false, then no error is in the objects error collection" do
|
31
|
+
klass = Class.new do
|
32
|
+
include Validatable
|
33
|
+
attr_accessor :name, :name_confirmation
|
34
|
+
validates_confirmation_of :name, :case_sensitive => false
|
35
|
+
end
|
36
|
+
instance = klass.new
|
37
|
+
instance.name = "foo"
|
38
|
+
instance.name_confirmation = "FOO"
|
39
|
+
assert_equal true, instance.valid?
|
40
|
+
end
|
41
|
+
|
42
|
+
test "given matching attributes of different case, when validated with case sensitive true, then error is in the objects error collection" do
|
43
|
+
klass = Class.new do
|
44
|
+
include Validatable
|
45
|
+
attr_accessor :name, :name_confirmation
|
46
|
+
validates_confirmation_of :name
|
47
|
+
end
|
48
|
+
instance = klass.new
|
49
|
+
instance.name = "foo"
|
50
|
+
instance.name_confirmation = "FOO"
|
51
|
+
assert_equal false, instance.valid?
|
52
|
+
assert_equal "doesn't match confirmation", instance.errors.on(:name)
|
53
|
+
|
54
|
+
end
|
17
55
|
end
|
18
56
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
module Functional
|
4
|
+
class ValidatesNumericalityOfTest < Test::Unit::TestCase
|
5
|
+
test "when validating numericality and the value is nil an error should exist on the instance" do
|
6
|
+
klass = Class.new do
|
7
|
+
include Validatable
|
8
|
+
attr_accessor :nothing
|
9
|
+
validates_numericality_of :nothing
|
10
|
+
end
|
11
|
+
instance = klass.new
|
12
|
+
instance.valid?
|
13
|
+
assert_equal "must be a number", instance.errors.on(:nothing)
|
14
|
+
end
|
15
|
+
|
16
|
+
test "when validating numericality and the value has a non numeric character an error should exist on the instance" do
|
17
|
+
klass = Class.new do
|
18
|
+
include Validatable
|
19
|
+
validates_numericality_of :some_string
|
20
|
+
|
21
|
+
def some_string
|
22
|
+
"some_string"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
instance = klass.new
|
26
|
+
instance.valid?
|
27
|
+
assert_equal "must be a number", instance.errors.on(:some_string)
|
28
|
+
end
|
29
|
+
|
30
|
+
test "when validating a number no error will be in the instance" do
|
31
|
+
klass = Class.new do
|
32
|
+
include Validatable
|
33
|
+
validates_numericality_of :valid_number
|
34
|
+
|
35
|
+
def valid_number
|
36
|
+
1.23
|
37
|
+
end
|
38
|
+
end
|
39
|
+
instance = klass.new
|
40
|
+
instance.valid?
|
41
|
+
assert_equal nil, instance.errors.on(:valid_number)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
module Functional
|
4
|
+
class ValidatesFormatOfTest < Test::Unit::TestCase
|
5
|
+
test "given invalid name, when validated, then error is in the objects error collection" do
|
6
|
+
klass = Class.new do
|
7
|
+
include Validatable
|
8
|
+
attr_accessor :name
|
9
|
+
validates_true_for :name, :logic => lambda { name == "nombre" }
|
10
|
+
end
|
11
|
+
instance = klass.new
|
12
|
+
instance.valid?
|
13
|
+
assert_equal "is invalid", instance.errors.on(:name)
|
14
|
+
end
|
15
|
+
|
16
|
+
test "given valid name, when validated, then no error is in the objects error collection" do
|
17
|
+
klass = Class.new do
|
18
|
+
include Validatable
|
19
|
+
attr_accessor :name
|
20
|
+
validates_true_for :name, :logic => lambda { name == "nombre" }
|
21
|
+
end
|
22
|
+
instance = klass.new
|
23
|
+
instance.name = "nombre"
|
24
|
+
assert_equal true, instance.valid?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -3,7 +3,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
|
3
3
|
module Unit
|
4
4
|
class ValidatableTest < Test::Unit::TestCase
|
5
5
|
expect false do
|
6
|
-
validation = stub(:valid? => false, :should_validate? => true, :attribute => "attribute", :message => "message", :level => 1)
|
6
|
+
validation = stub(:valid? => false, :should_validate? => true, :attribute => "attribute", :message => "message", :level => 1, :run_after_validate => nil)
|
7
7
|
klass = Class.new do
|
8
8
|
include Validatable
|
9
9
|
validations << validation
|
@@ -11,14 +11,6 @@ module Unit
|
|
11
11
|
klass.new.valid?
|
12
12
|
end
|
13
13
|
|
14
|
-
expect [:anything, :else] do
|
15
|
-
klass = Class.new do
|
16
|
-
include Validatable
|
17
|
-
include_validations_for :anything, :else
|
18
|
-
end
|
19
|
-
klass.send(:children_to_validate)
|
20
|
-
end
|
21
|
-
|
22
14
|
test "when validate is executed, then messages are added for each validation that fails" do
|
23
15
|
klass = Class.new do
|
24
16
|
include Validatable
|
@@ -12,4 +12,54 @@ class ValidatesConfirmationOfTest < Test::Unit::TestCase
|
|
12
12
|
instance = stub(:username=>"username", :username_confirmation=>"usessrname")
|
13
13
|
assert_equal false, validation.valid?(instance)
|
14
14
|
end
|
15
|
+
|
16
|
+
test "valid confirmation with case insensitive" do
|
17
|
+
validation = Validatable::ValidatesConfirmationOf.new :username
|
18
|
+
validation.case_sensitive = false
|
19
|
+
instance = stub(:username=>"username", :username_confirmation=>"USERNAME")
|
20
|
+
assert_equal true, validation.valid?(instance)
|
21
|
+
end
|
22
|
+
|
23
|
+
test "invalid confirmation with case sensitive" do
|
24
|
+
validation = Validatable::ValidatesConfirmationOf.new :username
|
25
|
+
validation.case_sensitive = true
|
26
|
+
instance = stub(:username=>"username", :username_confirmation=>"USERNAME")
|
27
|
+
assert_equal false, validation.valid?(instance)
|
28
|
+
end
|
29
|
+
|
30
|
+
test "invalid confirmation if value is nil and confirmation is not with case sensitive true" do
|
31
|
+
validation = Validatable::ValidatesConfirmationOf.new :username
|
32
|
+
validation.case_sensitive = true
|
33
|
+
assert_equal false, validation.valid?(stub(:username => nil, :username_confirmation => 'something'))
|
34
|
+
end
|
35
|
+
|
36
|
+
test "invalid confirmation if confirmation is nil and value is not with case sensitive true" do
|
37
|
+
validation = Validatable::ValidatesConfirmationOf.new :username
|
38
|
+
validation.case_sensitive = true
|
39
|
+
assert_equal false, validation.valid?(stub(:username => 'something', :username_confirmation => nil))
|
40
|
+
end
|
41
|
+
|
42
|
+
test "valid confirmation if value and confirmation are nil with case sensitive true" do
|
43
|
+
validation = Validatable::ValidatesConfirmationOf.new :username
|
44
|
+
validation.case_sensitive = true
|
45
|
+
assert_equal true, validation.valid?(stub(:username => nil, :username_confirmation => nil))
|
46
|
+
end
|
47
|
+
|
48
|
+
test "invalid confirmation if value is nil and confirmation is not with case sensitive false" do
|
49
|
+
validation = Validatable::ValidatesConfirmationOf.new :username
|
50
|
+
validation.case_sensitive = false
|
51
|
+
assert_equal false, validation.valid?(stub(:username => nil, :username_confirmation => 'something'))
|
52
|
+
end
|
53
|
+
|
54
|
+
test "invalid confirmation if confirmation is nil and value is not with case sensitive false" do
|
55
|
+
validation = Validatable::ValidatesConfirmationOf.new :username
|
56
|
+
validation.case_sensitive = false
|
57
|
+
assert_equal false, validation.valid?(stub(:username => 'something', :username_confirmation => nil))
|
58
|
+
end
|
59
|
+
|
60
|
+
test "valid confirmation if value and confirmation are nil with case sensitive false" do
|
61
|
+
validation = Validatable::ValidatesConfirmationOf.new :username
|
62
|
+
validation.case_sensitive = false
|
63
|
+
assert_equal true, validation.valid?(stub(:username => nil, :username_confirmation => nil))
|
64
|
+
end
|
15
65
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
module Unit
|
4
|
+
class ValidatesNumericalityOfTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
test "when the value is nil then valid is false" do
|
7
|
+
validation = Validatable::ValidatesNumericalityOf.new :nothing
|
8
|
+
instance = stub(:nothing => nil)
|
9
|
+
assert_equal false, validation.valid?(instance)
|
10
|
+
end
|
11
|
+
|
12
|
+
test "when value is an integer then valid is true" do
|
13
|
+
validation = Validatable::ValidatesNumericalityOf.new :some_int
|
14
|
+
instance = stub(:some_int => 50)
|
15
|
+
assert_equal true, validation.valid?(instance)
|
16
|
+
end
|
17
|
+
|
18
|
+
test "when value is an decimal then valid is true" do
|
19
|
+
validation = Validatable::ValidatesNumericalityOf.new :some_decimal
|
20
|
+
instance = stub(:some_decimal => 1.23)
|
21
|
+
assert_equal true, validation.valid?(instance)
|
22
|
+
end
|
23
|
+
|
24
|
+
test "when value has non numeric characters then valid is false" do
|
25
|
+
validation = Validatable::ValidatesNumericalityOf.new :some_non_numeric
|
26
|
+
instance = stub(:some_non_numeric => "50F")
|
27
|
+
assert_equal false, validation.valid?(instance)
|
28
|
+
end
|
29
|
+
|
30
|
+
test "when value is a string with multiple dots then valid is false" do
|
31
|
+
validation = Validatable::ValidatesNumericalityOf.new :multiple_dots
|
32
|
+
instance = stub(:multiple_dots => "50.0.0")
|
33
|
+
assert_equal false, validation.valid?(instance)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
class ValidatesTrueForTest < Test::Unit::TestCase
|
4
|
+
test "when block returns false for attribute value, then valid is false" do
|
5
|
+
validation = Validatable::ValidatesTrueFor.new :name
|
6
|
+
validation.logic = lambda { false }
|
7
|
+
assert_equal false, validation.valid?(stub_everything)
|
8
|
+
end
|
9
|
+
|
10
|
+
test "when block returns true for attribute value, then valid is false" do
|
11
|
+
validation = Validatable::ValidatesTrueFor.new :name
|
12
|
+
validation.logic = lambda { true }
|
13
|
+
assert_equal true, validation.valid?(stub_everything)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.
|
2
|
+
rubygems_version: 0.9.2
|
3
3
|
specification_version: 1
|
4
4
|
name: validatable
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.1
|
7
|
-
date: 2007-
|
6
|
+
version: 1.2.1
|
7
|
+
date: 2007-04-26 00:00:00 -04:00
|
8
8
|
summary: Validatable is a library for adding validations.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -25,17 +25,21 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
|
|
25
25
|
platform: ruby
|
26
26
|
signing_key:
|
27
27
|
cert_chain:
|
28
|
+
post_install_message:
|
28
29
|
authors:
|
29
30
|
- Jay Fields
|
30
31
|
files:
|
31
32
|
- lib/base.rb
|
33
|
+
- lib/child_validation.rb
|
32
34
|
- lib/errors.rb
|
33
35
|
- lib/validatable.rb
|
34
36
|
- lib/validations/validates_acceptance_of.rb
|
35
37
|
- lib/validations/validates_confirmation_of.rb
|
36
38
|
- lib/validations/validates_format_of.rb
|
37
39
|
- lib/validations/validates_length_of.rb
|
40
|
+
- lib/validations/validates_numericality_of.rb
|
38
41
|
- lib/validations/validates_presence_of.rb
|
42
|
+
- lib/validations/validates_true_for.rb
|
39
43
|
- lib/validations/validation_base.rb
|
40
44
|
- test/all_tests.rb
|
41
45
|
- test/test_helper.rb
|
@@ -44,14 +48,18 @@ files:
|
|
44
48
|
- test/functional/validates_confirmation_of_test.rb
|
45
49
|
- test/functional/validates_format_of_test.rb
|
46
50
|
- test/functional/validates_length_of_test.rb
|
51
|
+
- test/functional/validates_numericality_of_test.rb
|
47
52
|
- test/functional/validates_presence_of_test.rb
|
53
|
+
- test/functional/validates_true_for_test.rb
|
48
54
|
- test/unit/errors_test.rb
|
49
55
|
- test/unit/validatable_test.rb
|
50
56
|
- test/unit/validates_acceptance_of_test.rb
|
51
57
|
- test/unit/validates_confirmation_of_test.rb
|
52
58
|
- test/unit/validates_format_of_test.rb
|
53
59
|
- test/unit/validates_length_of_test.rb
|
60
|
+
- test/unit/validates_numericality_of_test.rb
|
54
61
|
- test/unit/validates_presence_of_test.rb
|
62
|
+
- test/unit/validates_true_for_test.rb
|
55
63
|
- test/unit/validation_base_test.rb
|
56
64
|
- rakefile.rb
|
57
65
|
- README
|