validatable 1.2.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. data/README +4 -10
  2. data/lib/requireable.rb +26 -0
  3. data/lib/understandable.rb +16 -10
  4. data/lib/validatable.rb +5 -1
  5. data/lib/validatable_assertions.rb +54 -0
  6. data/lib/validatable_class_methods.rb +18 -37
  7. data/lib/validatable_instance_methods.rb +8 -4
  8. data/lib/validation_assertion.rb +7 -0
  9. data/lib/validation_assertion_collector.rb +43 -0
  10. data/lib/validations/validates_confirmation_of.rb +2 -2
  11. data/lib/validations/validates_format_of.rb +1 -2
  12. data/lib/validations/validates_length_of.rb +3 -2
  13. data/lib/validations/validates_numericality_of.rb +5 -2
  14. data/lib/validations/validates_true_for.rb +1 -2
  15. data/lib/validations/validation_base.rb +52 -30
  16. data/rakefile.rb +1 -1
  17. data/test/functional/validatable_assertions_test.rb +98 -0
  18. data/test/functional/validatable_test.rb +52 -0
  19. data/test/functional/validates_length_of_test.rb +28 -2
  20. data/test/functional/validates_numericality_of_test.rb +12 -0
  21. data/test/functional/validation_assertion_collector_test.rb +49 -0
  22. data/test/test_helper.rb +20 -1
  23. data/test/unit/understandable_test.rb +21 -0
  24. data/test/unit/validatable_test.rb +0 -14
  25. data/test/unit/validates_acceptance_of_test.rb +1 -1
  26. data/test/unit/validates_confirmation_of_test.rb +9 -17
  27. data/test/unit/validates_format_of_test.rb +16 -7
  28. data/test/unit/validates_length_of_test.rb +34 -17
  29. data/test/unit/validates_numericality_of_test.rb +14 -1
  30. data/test/unit/validates_presence_of_test.rb +1 -1
  31. data/test/unit/validates_true_for_test.rb +15 -5
  32. data/test/unit/validation_base_test.rb +2 -2
  33. metadata +9 -2
data/README CHANGED
@@ -77,6 +77,8 @@ Validations can also be given groups. Groups can be used to validate an object w
77
77
  application.ssn = 377990118
78
78
  application.valid_for_saving? #=> true
79
79
  application.valid_for_underwriting? #=> false
80
+
81
+ As you can see, you can use an array if the validation needs to be part of various groups. However, if the validation only applies to one group you can simply use a symbol for the group name.
80
82
 
81
83
  Similar to Rails, Validatable also supports conditional validation.
82
84
 
@@ -106,19 +108,11 @@ Validatable also exposes an after_validate hook method.
106
108
  person.errors.on(:name) #=> "name can't be blank"
107
109
 
108
110
  The after_validate hook yields the result of the validation being run,
109
- the instance the validation was run on, and the attribute that was validate
111
+ the instance the validation was run on, and the attribute that was validated
110
112
 
111
113
  In the above example the attribute "name" is appended to the message.
112
114
 
113
115
  See the tests for more examples
114
116
 
115
117
  == Contributors
116
- Rick Bradley (Revision 25)
117
-
118
- Anonymous Z (Revision 29)
119
-
120
- Jason Miller (Revision 31)
121
-
122
- Ali Aghareza (Revision 43)
123
-
124
- Xavier Shay (Revision 48 & 49)
118
+ Rick Bradley, Anonymous Z, Jason Miller, Ali Aghareza, Xavier Shay
@@ -0,0 +1,26 @@
1
+ module Validatable
2
+ module Requireable #:nodoc:
3
+ module ClassMethods
4
+ def requires(*args)
5
+ required_options.concat args
6
+ end
7
+
8
+ def required_options
9
+ @required_options ||= []
10
+ end
11
+ end
12
+
13
+ def self.included(klass)
14
+ klass.extend ClassMethods
15
+ end
16
+
17
+ def requires(options)
18
+ required_options = self.class.required_options.inject([]) do |errors, attribute|
19
+ errors << attribute.to_s unless options.has_key?(attribute)
20
+ errors
21
+ end
22
+ raise ArgumentError.new("#{self.class} requires options: #{required_options.join(', ')}") if required_options.any?
23
+ true
24
+ end
25
+ end
26
+ end
@@ -1,21 +1,27 @@
1
1
  module Validatable
2
- module Understandable
3
- def understands(*args)
4
- understandings.concat args
5
- end
2
+ module Understandable #:nodoc:
3
+ module ClassMethods
4
+ def understands(*args)
5
+ understandings.concat args
6
+ end
6
7
 
7
- def understandings
8
- @understandings ||= []
8
+ def understandings
9
+ @understandings ||= []
10
+ end
11
+
12
+ def all_understandings
13
+ return understandings + self.superclass.all_understandings if self.superclass.respond_to? :all_understandings
14
+ understandings
15
+ end
9
16
  end
10
17
 
11
- def all_understandings
12
- return understandings + self.superclass.understandings if self.superclass.respond_to? :understandings
13
- understandings
18
+ def self.included(klass)
19
+ klass.extend ClassMethods
14
20
  end
15
21
 
16
22
  def must_understand(hash)
17
23
  invalid_options = hash.inject([]) do |errors, (key, value)|
18
- errors << key.to_s unless all_understandings.include?(key)
24
+ errors << key.to_s unless self.class.all_understandings.include?(key)
19
25
  errors
20
26
  end
21
27
  raise ArgumentError.new("invalid options: #{invalid_options.join(', ')}") if invalid_options.any?
@@ -4,6 +4,7 @@ require File.expand_path(File.dirname(__FILE__) + '/validatable_class_methods')
4
4
  require File.expand_path(File.dirname(__FILE__) + '/validatable_instance_methods')
5
5
  require File.expand_path(File.dirname(__FILE__) + '/child_validation')
6
6
  require File.expand_path(File.dirname(__FILE__) + '/understandable')
7
+ require File.expand_path(File.dirname(__FILE__) + '/requireable')
7
8
  require File.expand_path(File.dirname(__FILE__) + '/validations/validation_base')
8
9
  require File.expand_path(File.dirname(__FILE__) + '/validations/validates_format_of')
9
10
  require File.expand_path(File.dirname(__FILE__) + '/validations/validates_presence_of')
@@ -11,4 +12,7 @@ require File.expand_path(File.dirname(__FILE__) + '/validations/validates_accept
11
12
  require File.expand_path(File.dirname(__FILE__) + '/validations/validates_confirmation_of')
12
13
  require File.expand_path(File.dirname(__FILE__) + '/validations/validates_length_of')
13
14
  require File.expand_path(File.dirname(__FILE__) + '/validations/validates_true_for')
14
- require File.expand_path(File.dirname(__FILE__) + '/validations/validates_numericality_of')
15
+ require File.expand_path(File.dirname(__FILE__) + '/validations/validates_numericality_of')
16
+ require File.expand_path(File.dirname(__FILE__) + '/validation_assertion')
17
+ require File.expand_path(File.dirname(__FILE__) + '/validation_assertion_collector')
18
+ require File.expand_path(File.dirname(__FILE__) + '/validatable_assertions')
@@ -0,0 +1,54 @@
1
+ module ValidatableAssertions
2
+
3
+ def create_message_for_assertion(assertion)
4
+ message = "#{assertion.klass} does not contain a #{assertion.validation_type} for #{assertion.attribute}"
5
+ message += " with options #{assertion.options.inspect}" unless assertion.options == {}
6
+ message
7
+ end
8
+
9
+ def create_backtrace
10
+ backtrace = caller
11
+ backtrace.shift
12
+ backtrace.shift
13
+ backtrace
14
+ end
15
+
16
+ def validation_matching_proc(assertion)
17
+ lambda do |validation|
18
+ result = assertion.validation_type === validation
19
+ result &&= assertion.attribute == validation.attribute
20
+ assertion.options.each_pair do |key, value|
21
+ validation_value = validation.send key if validation.respond_to? key
22
+ result = false if validation_value.nil?
23
+ result &&= validation_value == value
24
+ end
25
+ result
26
+ end
27
+ end
28
+
29
+ def self.included(klass)
30
+ Test::Unit::TestCase.class_eval do
31
+ def self.create_test_name(assertion)
32
+ "test#{assertion.validation_type.to_s.gsub(/Validatable::/,'').gsub(/([A-Z])/, '_\1').downcase}_#{assertion.attribute}"
33
+ end
34
+
35
+ def self.define_test_method name, &block
36
+ class_eval do
37
+ define_method name, &block
38
+ end
39
+ end
40
+ end
41
+
42
+ Class.class_eval do
43
+ def must_validate(&block)
44
+ test_class = eval "self", block.binding
45
+ ValidationAssertionCollector.gather(self, &block).each do |assertion|
46
+ test_class.define_test_method test_class.create_test_name(assertion) do
47
+ validation = assertion.klass.validations.find &validation_matching_proc(assertion)
48
+ add_failure create_message_for_assertion(assertion), create_backtrace if validation.nil?
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -20,9 +20,7 @@ module Validatable
20
20
  # * with - The regular expression used to validate the format
21
21
  # * group - The group that this validation belongs to. A validation can belong to multiple groups
22
22
  def validates_format_of(*args)
23
- add_validations(args, ValidatesFormatOf) do |validation, options|
24
- validation.with = options[:with]
25
- end
23
+ add_validations(args, ValidatesFormatOf)
26
24
  end
27
25
 
28
26
  # call-seq: validates_length_of(*args)
@@ -43,13 +41,11 @@ module Validatable
43
41
  # * if - A block that when executed must return true of the validation will not occur
44
42
  # * minimum - The minimum size of the attribute
45
43
  # * maximum - The maximum size of the attribute
44
+ # * is - The size the attribute must be
45
+ # * within - A range that the size of the attribute must fall within
46
46
  # * group - The group that this validation belongs to. A validation can belong to multiple groups
47
47
  def validates_length_of(*args)
48
- add_validations(args, ValidatesLengthOf) do |validation, options|
49
- validation.minimum = options[:minimum]
50
- validation.maximum = options[:maximum]
51
- validation.is = options[:is]
52
- end
48
+ add_validations(args, ValidatesLengthOf)
53
49
  end
54
50
 
55
51
  # call-seq: validates_numericality_of(*args)
@@ -68,6 +64,7 @@ module Validatable
68
64
  # * level - The level at which the validation should occur
69
65
  # * if - A block that when executed must return true of the validation will not occur
70
66
  # * group - The group that this validation belongs to. A validation can belong to multiple groups
67
+ # * only_integer - Whether the attribute must be an integer (default is false)
71
68
  def validates_numericality_of(*args)
72
69
  add_validations(args, ValidatesNumericalityOf)
73
70
  end
@@ -117,13 +114,7 @@ module Validatable
117
114
  # * if - A block that when executed must return true of the validation will not occur
118
115
  # * group - The group that this validation belongs to. A validation can belong to multiple groups
119
116
  def validates_confirmation_of(*args)
120
- add_validations(args, ValidatesConfirmationOf) do |validation, options|
121
- validation.case_sensitive = if options.has_key? :case_sensitive
122
- options[:case_sensitive]
123
- else
124
- true
125
- end
126
- end
117
+ add_validations(args, ValidatesConfirmationOf)
127
118
  end
128
119
 
129
120
  # call-seq: validates_presence_of(*args)
@@ -168,9 +159,7 @@ module Validatable
168
159
  # * group - The group that this validation belongs to. A validation can belong to multiple groups
169
160
  # * logic - A block that executes to perform the validation
170
161
  def validates_true_for(*args)
171
- add_validations(args, ValidatesTrueFor) do |validation, options|
172
- validation.logic = options[:logic]
173
- end
162
+ add_validations(args, ValidatesTrueFor)
174
163
  end
175
164
 
176
165
  # call-seq: include_validations_for(attribute_to_validate, options = {})
@@ -206,25 +195,13 @@ module Validatable
206
195
  children_to_validate << ChildValidation.new(attribute_to_validate, options[:map] || {}, options[:if] || lambda { true })
207
196
  end
208
197
 
209
- def validate(instance) #:nodoc:
210
- levels = self.validations.collect { |validation| validation.level }.uniq
211
- levels.sort.each do |level|
212
- self.validations.select { |validation| validation.level == level }.each do |validation|
213
- if validation.should_validate?(instance)
214
- instance.errors.add(validation.attribute, validation.message) unless validation.valid?(instance)
215
- end
216
- end
217
- return if instance.errors.any?
218
- end
219
- end
220
-
221
198
  def validate_children(instance, groups) #:nodoc:
222
199
  self.children_to_validate.each do |child_validation|
223
200
  next unless child_validation.should_validate?(instance)
224
201
  child = instance.send child_validation.attribute
225
202
  child.valid?(*groups)
226
203
  child.errors.each do |attribute, message|
227
- instance.errors.add(child_validation.map[attribute.to_sym] || attribute, message)
204
+ add_error(instance, child_validation.map[attribute.to_sym] || attribute, message)
228
205
  end
229
206
  end
230
207
  end
@@ -232,23 +209,26 @@ module Validatable
232
209
  def validations #:nodoc:
233
210
  @validations ||= []
234
211
  end
235
-
212
+
213
+ def add_error(instance, attribute, message) #:nodoc:
214
+ instance.errors.add(attribute, message)
215
+ end
216
+
236
217
  protected
218
+
237
219
  def add_validations(args, klass) #:nodoc:
238
220
  options = args.last.is_a?(Hash) ? args.pop : {}
239
221
  args.each do |attribute|
240
- klass.must_understand options
241
222
  new_validation = klass.new attribute, options
242
- yield new_validation, options if block_given?
243
223
  self.validations << new_validation
244
- self.create_valid_method_for_groups new_validation.groups
224
+ self.create_valid_method_for_groups new_validation.groups
245
225
  end
246
226
  end
247
227
 
248
- def create_valid_method_for_groups(groups)
228
+ def create_valid_method_for_groups(groups) #:nodoc:
249
229
  groups.each do |group|
250
230
  self.class_eval do
251
- define_method :"valid_for_#{group}?" do
231
+ define_method "valid_for_#{group}?".to_sym do
252
232
  valid_for_group?(group)
253
233
  end
254
234
  end
@@ -258,5 +238,6 @@ module Validatable
258
238
  def children_to_validate #:nodoc:
259
239
  @children_to_validate ||= []
260
240
  end
241
+
261
242
  end
262
243
  end
@@ -18,7 +18,7 @@ module Validatable
18
18
  end
19
19
 
20
20
  protected
21
- def valid_for_group?(*groups)
21
+ def valid_for_group?(*groups) #:nodoc:
22
22
  errors.clear
23
23
  self.class.validate_children(self, groups)
24
24
  self.validate(groups)
@@ -36,18 +36,22 @@ module Validatable
36
36
 
37
37
  def run_validation(validation) #:nodoc:
38
38
  validation_result = validation.valid?(self)
39
- self.errors.add(validation.attribute, validation.message) unless validation_result
39
+ add_error(validation.attribute, validation.message) unless validation_result
40
40
  validation.run_after_validate(validation_result, self, validation.attribute)
41
41
  end
42
42
 
43
- def validations_for_level_and_groups(level, groups)
43
+ def add_error(attribute, message) #:nodoc:
44
+ self.class.add_error(self, attribute, message)
45
+ end
46
+
47
+ def validations_for_level_and_groups(level, groups) #:nodoc:
44
48
  validations_for_level = self.validations.select { |validation| validation.level == level }
45
49
  return validations_for_level if groups.empty?
46
50
  validations_for_level.select { |validation| (groups & validation.groups).any? }
47
51
  end
48
52
 
49
53
  def validation_levels #:nodoc:
50
- self.validations.collect { |validation| validation.level }.uniq.sort
54
+ self.validations.inject([1]) { |accum,validation| accum << validation.level }.uniq.sort
51
55
  end
52
56
 
53
57
  def validations #:nodoc:
@@ -0,0 +1,7 @@
1
+ class ValidationAssertion
2
+ attr_accessor :klass, :validation_type, :options, :attribute
3
+
4
+ def initialize(klass, validation_type, attribute)
5
+ self.klass, self.validation_type, self.attribute, self.options = klass, validation_type, attribute, {}
6
+ end
7
+ end
@@ -0,0 +1,43 @@
1
+ class ValidationAssertionCollector
2
+ def self.gather(klass, &block)
3
+ collector = self.new(klass)
4
+ collector.instance_eval(&block)
5
+ collector.assertions
6
+ end
7
+
8
+ def self.define_method_for_validation_method(validation_method, validatable_class)
9
+ define_method validation_method.gsub(/^validates_/,'').to_sym do |attribute|
10
+ assertions << ValidationAssertion.new(self.klass, validatable_class, attribute)
11
+ define_methods_on_assertion_to_collect_options validatable_class, assertions.last
12
+ end
13
+ end
14
+
15
+ Validatable::ClassMethods.public_instance_methods.sort.grep(/^validates_/).each do |validation_method|
16
+ next if validation_method == 'validates_true_for'
17
+ validatable_class = Validatable.const_get(validation_method.split(/_/).collect { |word| word.capitalize}.join)
18
+ define_method_for_validation_method(validation_method, validatable_class)
19
+ end
20
+
21
+ attr_accessor :klass
22
+
23
+ def initialize(klass)
24
+ self.klass = klass
25
+ end
26
+
27
+ def define_methods_on_assertion_to_collect_options(validatable_class, assertion)
28
+ validatable_class.all_understandings.each do |option|
29
+ next if option == :if
30
+ class << assertion; self; end.instance_eval do
31
+ define_method option do |value|
32
+ self.options.merge!(option=>value)
33
+ self
34
+ end
35
+ end
36
+ end
37
+ assertion
38
+ end
39
+
40
+ def assertions
41
+ @assertions ||= []
42
+ end
43
+ end
@@ -1,7 +1,7 @@
1
1
  module Validatable
2
2
  class ValidatesConfirmationOf < ValidationBase #:nodoc:
3
- attr_accessor :case_sensitive
4
- understands :case_sensitive
3
+ option :case_sensitive
4
+ default :case_sensitive => true
5
5
 
6
6
  def valid?(instance)
7
7
  return instance.send(self.attribute) == instance.send("#{self.attribute}_confirmation".to_sym) if case_sensitive
@@ -1,7 +1,6 @@
1
1
  module Validatable
2
2
  class ValidatesFormatOf < ValidationBase #:nodoc:
3
- attr_accessor :with
4
- understands :with
3
+ required_option :with
5
4
 
6
5
  def valid?(instance)
7
6
  not (instance.send(self.attribute).to_s =~ self.with).nil?
@@ -1,7 +1,6 @@
1
1
  module Validatable
2
2
  class ValidatesLengthOf < ValidationBase #:nodoc:
3
- attr_accessor :minimum, :maximum, :is
4
- understands :minimum, :maximum, :is
3
+ option :minimum, :maximum, :is, :within
5
4
 
6
5
  def message
7
6
  super || "is invalid"
@@ -10,9 +9,11 @@ module Validatable
10
9
  def valid?(instance)
11
10
  valid = true
12
11
  value = instance.send(self.attribute) || ""
12
+
13
13
  valid &&= value.length <= maximum unless maximum.nil?
14
14
  valid &&= value.length >= minimum unless minimum.nil?
15
15
  valid &&= value.length == is unless is.nil?
16
+ valid &&= within.include?(value.length) unless within.nil?
16
17
  valid
17
18
  end
18
19
  end
@@ -1,8 +1,11 @@
1
1
  module Validatable
2
2
  class ValidatesNumericalityOf < ValidationBase #:nodoc:
3
-
3
+ option :only_integer
4
+
4
5
  def valid?(instance)
5
- not (instance.send(self.attribute).to_s =~ /^\d*\.{0,1}\d+$/).nil?
6
+ value = instance.send(self.attribute).to_s
7
+ regex = self.only_integer ? /\A[+-]?\d+\Z/ : /^\d*\.{0,1}\d+$/
8
+ not (value =~ regex).nil?
6
9
  end
7
10
 
8
11
  def message
@@ -1,7 +1,6 @@
1
1
  module Validatable
2
2
  class ValidatesTrueFor < ValidationBase #:nodoc:
3
- attr_accessor :logic
4
- understands :logic
3
+ required_option :logic
5
4
 
6
5
  def valid?(instance)
7
6
  instance.instance_eval(&logic) == true
@@ -1,26 +1,63 @@
1
1
  module Validatable
2
2
  class ValidationBase #:nodoc:
3
- extend Understandable
4
- understands :message, :if, :times, :level, :groups
5
-
6
- attr_accessor :attribute, :message, :times
7
- attr_reader :level, :groups
3
+ class << self
4
+ def required_option(*args)
5
+ option(*args)
6
+ requires(*args)
7
+ end
8
+
9
+ def option(*args)
10
+ attr_accessor(*args)
11
+ understands(*args)
12
+ end
13
+
14
+ def default(hash)
15
+ defaults.merge! hash
16
+ end
17
+
18
+ def defaults
19
+ @defaults ||= {}
20
+ end
21
+
22
+ def all_defaults
23
+ return defaults.merge(self.superclass.all_defaults) if self.superclass.respond_to? :all_defaults
24
+ defaults
25
+ end
26
+
27
+ def after_validate(&block)
28
+ after_validations << block
29
+ end
30
+
31
+ def after_validations
32
+ @after_validations ||= []
33
+ end
34
+
35
+ def all_after_validations
36
+ return after_validations + self.superclass.all_after_validations if self.superclass.respond_to? :all_after_validations
37
+ after_validations
38
+ end
39
+ end
40
+
41
+ include Understandable
42
+ include Requireable
43
+
44
+ option :message, :if, :times, :level, :groups
45
+ default :if => lambda { true }, :level => 1, :groups => []
46
+ attr_accessor :attribute
8
47
 
9
48
  def initialize(attribute, options={})
10
- @attribute = attribute
11
- @message = options[:message]
12
- @conditional = options[:if] || Proc.new { true }
13
- @times = options[:times]
14
- @level = options[:level] || 1
15
- @groups = case options[:groups]
16
- when nil then []
17
- when Array then options[:groups]
18
- else [options[:groups]]
49
+ must_understand options
50
+ requires options
51
+ self.class.all_understandings.each do |understanding|
52
+ options[understanding] = self.class.all_defaults[understanding] unless options.has_key? understanding
53
+ self.instance_variable_set("@#{understanding}", options[understanding])
19
54
  end
55
+ self.attribute = attribute
56
+ self.groups = [self.groups] unless self.groups.is_a?(Array)
20
57
  end
21
58
 
22
59
  def should_validate?(instance)
23
- instance.instance_eval(&@conditional) && validate_this_time?
60
+ instance.instance_eval(&self.if) && validate_this_time?
24
61
  end
25
62
 
26
63
  def validate_this_time?
@@ -34,20 +71,5 @@ module Validatable
34
71
  block.call result, instance, attribute
35
72
  end
36
73
  end
37
-
38
- class << self
39
- def after_validate(&block)
40
- after_validations << block
41
- end
42
-
43
- def after_validations
44
- @after_validations ||= []
45
- end
46
-
47
- def all_after_validations
48
- return after_validations + self.superclass.after_validations if self.superclass.respond_to? :after_validations
49
- after_validations
50
- end
51
- end
52
74
  end
53
75
  end
@@ -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.2.2"
32
+ s.version = "1.3.0"
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'
@@ -0,0 +1,98 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class ValidatableAssertionsTest < Test::Unit::TestCase
4
+ expect "Klass does not contain a ValidationType for Attribute" do
5
+ klass = Class.new do
6
+ include ValidatableAssertions
7
+ end
8
+ klass.new.create_message_for_assertion(stub(:klass=>"Klass", :validation_type=>"ValidationType", :attribute=>"Attribute", :options=>{}))
9
+ end
10
+
11
+ expect "Klass does not contain a ValidationType for Attribute" do
12
+ klass = Class.new do
13
+ include ValidatableAssertions
14
+ end
15
+ klass.new.create_message_for_assertion(stub(:klass=>"Klass", :validation_type=>"ValidationType", :attribute=>"Attribute", :options=>{}))
16
+ end
17
+
18
+ expect false do
19
+ klass = Class.new do
20
+ include ValidatableAssertions
21
+ end
22
+ assertion = stub(:validation_type=>stub(:=== => true), :attribute => "attribute", :options=>{:level => 1, :times => 2})
23
+ validation = stub(:validation_type=>"validation_type", :attribute => "attribute", :level => 2, :times => 2)
24
+ klass.new.validation_matching_proc(assertion).call(validation)
25
+ end
26
+
27
+ expect false do
28
+ klass = Class.new do
29
+ include ValidatableAssertions
30
+ end
31
+ assertion = stub(:validation_type=>stub(:=== => true), :attribute => "non matching attribute", :options=>{})
32
+ validation = stub(:validation_type=>"validation_type", :attribute => nil)
33
+ klass.new.validation_matching_proc(assertion).call(validation)
34
+ end
35
+
36
+ expect false do
37
+ klass = Class.new do
38
+ include ValidatableAssertions
39
+ end
40
+ assertion = stub(:validation_type=>"non matching validation_type", :options=>{})
41
+ validation = stub(:validation_type=>"validation_type")
42
+ klass.new.validation_matching_proc(assertion).call(validation)
43
+ end
44
+
45
+ expect true do
46
+ klass = Class.new do
47
+ include ValidatableAssertions
48
+ end
49
+ assertion = stub(:validation_type=>stub(:=== => true), :attribute => "attribute", :options=>{:level => 1, :times => 2})
50
+ validation = stub(:validation_type=>"validation_type", :attribute => "attribute", :level => 1, :times => 2)
51
+ klass.new.validation_matching_proc(assertion).call(validation)
52
+ end
53
+
54
+ expect true do
55
+ Class.new do
56
+ include ValidatableAssertions
57
+ end
58
+
59
+ Class.respond_to? :must_validate
60
+ end
61
+
62
+ expect "test_validates_presence_of_name" do
63
+ test_class = Class.new(Test::Unit::TestCase) do
64
+ include ValidatableAssertions
65
+ end
66
+ test_class.create_test_name(stub(:validation_type=>Validatable::ValidatesPresenceOf, :attribute=>:name))
67
+ end
68
+
69
+ expect true do
70
+ test_class = Class.new(Test::Unit::TestCase) do
71
+ include ValidatableAssertions
72
+ end
73
+
74
+ test_class.define_test_method :some_test do
75
+ true
76
+ end
77
+
78
+ test_class.instance_methods.include? "some_test"
79
+ end
80
+
81
+ expect true do
82
+ klass = Class.new do
83
+ include Validatable
84
+ end
85
+ test_class = Class.new Test::Unit::TestCase do
86
+ include ValidatableAssertions
87
+
88
+ klass.must_validate do
89
+ presence_of :anything
90
+ end
91
+
92
+ end
93
+
94
+ test_class.any_instance.expects(:add_failure)
95
+ test_class.new(:test_validates_presence_of_anything).test_validates_presence_of_anything
96
+ true
97
+ end
98
+ end
@@ -35,6 +35,58 @@ module Functional
35
35
  assert_equal "can't be empty", instance.errors.on(:name)
36
36
  end
37
37
 
38
+
39
+ test "when child validations have errors, level 2 and higher parent validations are not performed" do
40
+ child_class = Class.new do
41
+ include Validatable
42
+ attr_accessor :name
43
+ validates_presence_of :name
44
+ end
45
+ klass = Class.new do
46
+ include Validatable
47
+ extend Forwardable
48
+
49
+ def_delegator :child, :name
50
+
51
+ validates_true_for :name, :logic => lambda { false }, :level => 2, :message => "invalid message"
52
+
53
+ include_validations_for :child
54
+
55
+ define_method :child do
56
+ @child ||= child_class.new
57
+ end
58
+
59
+ end
60
+ instance = klass.new
61
+ instance.valid?
62
+ assert_equal "can't be empty", instance.errors.on(:name)
63
+ end
64
+
65
+ test "when child validations have errors, level 1 parent validations are still performed" do
66
+ child_class = Class.new do
67
+ include Validatable
68
+ attr_accessor :name
69
+ validates_presence_of :name
70
+
71
+ end
72
+ klass = Class.new do
73
+ include Validatable
74
+
75
+ validates_true_for :address, :logic => lambda { false }, :level => 1, :message => "invalid message"
76
+
77
+ include_validations_for :child
78
+
79
+ define_method :child do
80
+ @child ||= child_class.new
81
+ end
82
+
83
+ end
84
+ instance = klass.new
85
+ instance.valid?
86
+ assert_equal "can't be empty", instance.errors.on(:name)
87
+ assert_equal "invalid message", instance.errors.on(:address)
88
+ end
89
+
38
90
  test "given a child class with validations, the error is in the parent objects error collection as the mapped attribute" do
39
91
  child_class = Class.new do
40
92
  include Validatable
@@ -13,23 +13,49 @@ module Functional
13
13
  assert_equal "is invalid", instance.errors.on(:name)
14
14
  end
15
15
 
16
- test "given exact value, when validated, then error is in the objects error collection" do
16
+ test "given is constraint, when validated, then error is in the objects error collection" do
17
17
  klass = Class.new do
18
18
  include Validatable
19
19
  attr_accessor :name
20
20
  validates_length_of :name, :is => 2
21
21
  end
22
+
22
23
  instance = klass.new
23
24
  instance.valid?
24
25
  assert_equal "is invalid", instance.errors.on(:name)
25
26
  end
26
27
 
27
- test "given exact value is met, when validated, then valid is true" do
28
+ test "given is constraint is met, when validated, then valid is true" do
28
29
  klass = Class.new do
29
30
  include Validatable
30
31
  attr_accessor :name
31
32
  validates_length_of :name, :is => 2
32
33
  end
34
+
35
+ instance = klass.new
36
+ instance.name = "bk"
37
+ assert_equal true, instance.valid?
38
+ end
39
+
40
+ test "given within constraint, when validated, then error is in the objects error collection" do
41
+ klass = Class.new do
42
+ include Validatable
43
+ attr_accessor :name
44
+ validates_length_of :name, :within => 2..4
45
+ end
46
+
47
+ instance = klass.new
48
+ instance.valid?
49
+ assert_equal "is invalid", instance.errors.on(:name)
50
+ end
51
+
52
+ test "given within constraint, when validated, then valid is true" do
53
+ klass = Class.new do
54
+ include Validatable
55
+ attr_accessor :name
56
+ validates_length_of :name, :within => 2..4
57
+ end
58
+
33
59
  instance = klass.new
34
60
  instance.name = "bk"
35
61
  assert_equal true, instance.valid?
@@ -41,5 +41,17 @@ module Functional
41
41
  assert_equal nil, instance.errors.on(:valid_number)
42
42
  end
43
43
 
44
+ test "when validating an integer and the value is a decimal an error should exist on the instance" do
45
+ klass = Class.new do
46
+ include Validatable
47
+ validates_numericality_of :valid_number, :only_integer => true
48
+ attr_accessor :valid_number
49
+ end
50
+
51
+ instance = klass.new
52
+ instance.valid_number = 1.23
53
+ instance.valid?
54
+ assert_equal "must be a number", instance.errors.on(:valid_number)
55
+ end
44
56
  end
45
57
  end
@@ -0,0 +1,49 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class ValidationAssertionCollectorTest < Test::Unit::TestCase
4
+ expect 1 do
5
+ assertions = ValidationAssertionCollector.gather(Class.new) do
6
+ presence_of :name
7
+ end
8
+ assertions.size
9
+ end
10
+
11
+ expect "save this message" do
12
+ assertions = ValidationAssertionCollector.gather(Class.new) do
13
+ presence_of(:name).message("ignore this message").message("save this message")
14
+ end
15
+ assertions.first.options[:message]
16
+ end
17
+
18
+ expect :class_being_validated do
19
+ assertions = ValidationAssertionCollector.gather(:class_being_validated) do
20
+ presence_of(:name)
21
+ end
22
+ assertions.first.klass
23
+ end
24
+
25
+ expect NoMethodError do
26
+ assertions = ValidationAssertionCollector.gather(Class.new) do
27
+ presence_of(:name).invalid_option
28
+ end
29
+ end
30
+
31
+ expect NoMethodError do
32
+ assertions = ValidationAssertionCollector.gather(Class.new) do
33
+ true_for(:name)
34
+ end
35
+ end
36
+
37
+ expect NoMethodError do
38
+ assertions = ValidationAssertionCollector.gather(Class.new) do
39
+ presence_of(:name).if lambda { true }
40
+ end
41
+ end
42
+
43
+ expect Validatable::ValidatesPresenceOf do
44
+ assertions = ValidationAssertionCollector.gather(Class.new) do
45
+ presence_of(:name)
46
+ end
47
+ assertions.first.validation_type
48
+ end
49
+ end
@@ -1,6 +1,8 @@
1
1
  require 'test/unit'
2
2
  require 'rubygems'
3
3
  require 'mocha'
4
+ require 'set'
5
+
4
6
  require File.dirname(__FILE__) + '/../lib/validatable'
5
7
 
6
8
  class << Test::Unit::TestCase
@@ -12,7 +14,24 @@ class << Test::Unit::TestCase
12
14
 
13
15
  def expect(expected_value, &block)
14
16
  define_method :"test_#{caller.first.split("/").last}" do
15
- assert_equal expected_value, instance_eval(&block)
17
+ begin
18
+ assert_equal expected_value, instance_eval(&block)
19
+ rescue Exception => ex
20
+ raise ex unless expected_value.is_a?(Class) && ex.is_a?(expected_value)
21
+ assert_equal expected_value, ex.class
22
+ end
16
23
  end
17
24
  end
25
+ end
26
+
27
+ class Test::Unit::TestCase
28
+ def assert_array_equal a, b
29
+ assert_equal Set.new(a), Set.new(b)
30
+ end
31
+ end
32
+
33
+ class Array
34
+ def to_blank_options_hash
35
+ self.inject({}) {|hash, value| hash[value] = nil; hash }
36
+ end
18
37
  end
@@ -0,0 +1,21 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class UnderstandableTest < Test::Unit::TestCase
4
+ test "all understandings should collect understandings from all super classes" do
5
+ a = Class.new do
6
+ include Validatable::Understandable
7
+ understands :a
8
+ end
9
+
10
+ b = Class.new(a) do
11
+ include Validatable::Understandable
12
+ understands :b
13
+ end
14
+ c = Class.new(b) do
15
+ include Validatable::Understandable
16
+ understands :c
17
+ end
18
+
19
+ assert_array_equal [:a, :b, :c], c.all_understandings
20
+ end
21
+ end
@@ -10,20 +10,6 @@ module Unit
10
10
  end
11
11
  klass.new.valid?
12
12
  end
13
-
14
- test "when validate is executed, then messages are added for each validation that fails" do
15
- klass = Class.new do
16
- include Validatable
17
- end
18
- klass.send(:validations) << stub(:valid? => false, :should_validate? => true, :attribute => 'attribute', :message => 'message', :level => 1)
19
- klass.send(:validations) << stub(:valid? => false, :should_validate? => true, :attribute => 'attribute2', :message => 'message2', :level => 1)
20
- instance=mock
21
- instance.expects(:errors).returns(errors=mock).times 3
22
- errors.expects(:add).with('attribute', 'message')
23
- errors.expects(:add).with('attribute2', 'message2')
24
- errors.expects(:any?).returns false
25
- klass.validate(instance)
26
- end
27
13
 
28
14
  expect true do
29
15
  klass = Class.new do
@@ -14,7 +14,7 @@ class ValidatesAcceptanceOfTest < Test::Unit::TestCase
14
14
  end
15
15
 
16
16
  expect true do
17
- Validatable::ValidatesAcceptanceOf.must_understand(:message => nil, :if => nil, :times => nil, :level => nil, :groups => nil)
17
+ Validatable::ValidatesAcceptanceOf.new(:test).must_understand(:message => nil, :if => nil, :times => nil, :level => nil, :groups => nil)
18
18
  end
19
19
 
20
20
  end
@@ -14,58 +14,50 @@ class ValidatesConfirmationOfTest < Test::Unit::TestCase
14
14
  end
15
15
 
16
16
  test "valid confirmation with case insensitive" do
17
- validation = Validatable::ValidatesConfirmationOf.new :username
18
- validation.case_sensitive = false
17
+ validation = Validatable::ValidatesConfirmationOf.new :username, :case_sensitive => false
19
18
  instance = stub(:username=>"username", :username_confirmation=>"USERNAME")
20
19
  assert_equal true, validation.valid?(instance)
21
20
  end
22
21
 
23
22
  test "invalid confirmation with case sensitive" do
24
- validation = Validatable::ValidatesConfirmationOf.new :username
25
- validation.case_sensitive = true
23
+ validation = Validatable::ValidatesConfirmationOf.new :username, :case_sensitive => true
26
24
  instance = stub(:username=>"username", :username_confirmation=>"USERNAME")
27
25
  assert_equal false, validation.valid?(instance)
28
26
  end
29
27
 
30
28
  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
29
+ validation = Validatable::ValidatesConfirmationOf.new :username, :case_sensitive => true
33
30
  assert_equal false, validation.valid?(stub(:username => nil, :username_confirmation => 'something'))
34
31
  end
35
32
 
36
33
  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
34
+ validation = Validatable::ValidatesConfirmationOf.new :username, :case_sensitive => true
39
35
  assert_equal false, validation.valid?(stub(:username => 'something', :username_confirmation => nil))
40
36
  end
41
37
 
42
38
  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
39
+ validation = Validatable::ValidatesConfirmationOf.new :username, :case_sensitive => true
45
40
  assert_equal true, validation.valid?(stub(:username => nil, :username_confirmation => nil))
46
41
  end
47
42
 
48
43
  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
44
+ validation = Validatable::ValidatesConfirmationOf.new :username, :case_sensitive => false
51
45
  assert_equal false, validation.valid?(stub(:username => nil, :username_confirmation => 'something'))
52
46
  end
53
47
 
54
48
  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
49
+ validation = Validatable::ValidatesConfirmationOf.new :username, :case_sensitive => false
57
50
  assert_equal false, validation.valid?(stub(:username => 'something', :username_confirmation => nil))
58
51
  end
59
52
 
60
53
  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
54
+ validation = Validatable::ValidatesConfirmationOf.new :username, :case_sensitive => false
63
55
  assert_equal true, validation.valid?(stub(:username => nil, :username_confirmation => nil))
64
56
  end
65
57
 
66
58
  expect true do
67
59
  options = { :message => nil, :if => nil, :times => nil, :level => nil, :groups => nil, :case_sensitive => nil }
68
- Validatable::ValidatesConfirmationOf.must_understand(options)
60
+ Validatable::ValidatesConfirmationOf.new(:test).must_understand(options)
69
61
  end
70
62
 
71
63
  end
@@ -2,25 +2,34 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
2
 
3
3
  class ValidatesFormatOfTest < Test::Unit::TestCase
4
4
  test "when attribute value does not match the given regex, then valid is false" do
5
- validation = Validatable::ValidatesFormatOf.new :name
6
- validation.with = /book/
5
+ validation = Validatable::ValidatesFormatOf.new :name, :with => /book/
7
6
  assert_equal false, validation.valid?(stub_everything)
8
7
  end
9
8
 
10
9
  test "when attribute value does match the given regex, then valid is true" do
11
- validation = Validatable::ValidatesFormatOf.new :name
12
- validation.with = /book/
10
+ validation = Validatable::ValidatesFormatOf.new :name, :with => /book/
13
11
  assert_equal true, validation.valid?(stub(:name=>"book"))
14
12
  end
15
13
 
16
14
  test "when attribute value is an integer it should be converted to a string before matching" do
17
- validation = Validatable::ValidatesFormatOf.new :age
18
- validation.with = /14/
15
+ validation = Validatable::ValidatesFormatOf.new :age, :with => /14/
19
16
  assert_equal true, validation.valid?(stub(:age=>14))
20
17
  end
21
18
 
19
+ test "when no with is given, then an error is raised during construction" do
20
+ assert_raises ArgumentError do
21
+ validation = Validatable::ValidatesFormatOf.new :age
22
+ end
23
+ end
24
+
25
+ expect true do
26
+ options = [:message, :if, :times, :level, :groups, :with]
27
+ Validatable::ValidatesFormatOf.new(:test, options.to_blank_options_hash).must_understand(options.to_blank_options_hash)
28
+ end
29
+
22
30
  expect true do
23
- Validatable::ValidatesFormatOf.must_understand(:message => nil, :if => nil, :times => nil, :level => nil, :groups => nil, :with => nil)
31
+ options = [:with]
32
+ Validatable::ValidatesFormatOf.new(:name, options.to_blank_options_hash).requires(options.to_blank_options_hash)
24
33
  end
25
34
 
26
35
  end
@@ -2,46 +2,63 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
2
 
3
3
  module Unit
4
4
  class ValidatesLengthOfTest < Test::Unit::TestCase
5
-
6
5
  test "max length" do
7
- validation = Validatable::ValidatesLengthOf.new :username
8
- validation.maximum = 8
6
+ validation = Validatable::ValidatesLengthOf.new :username, :maximum => 8
9
7
  instance = stub(:username=>"usernamefdfd")
10
8
  assert_equal false, validation.valid?(instance)
11
9
  end
12
10
 
13
11
  test "min length" do
14
- validation = Validatable::ValidatesLengthOf.new :username
15
- validation.minimum = 2
12
+ validation = Validatable::ValidatesLengthOf.new :username, :minimum => 2
16
13
  instance = stub(:username=>"u")
17
14
  assert_equal false, validation.valid?(instance)
18
15
  end
19
16
 
17
+ test "valid length" do
18
+ validation = Validatable::ValidatesLengthOf.new :username, :minimum => 2, :maximum => 8
19
+ instance = stub(:username=>"udfgdf")
20
+ assert_equal true, validation.valid?(instance)
21
+ end
22
+
20
23
  test "is length is false" do
21
- validation = Validatable::ValidatesLengthOf.new :username
22
- validation.is = 2
24
+ validation = Validatable::ValidatesLengthOf.new :username, :is => 2
23
25
  instance = stub(:username=>"u")
24
26
  assert_equal false, validation.valid?(instance)
25
27
  end
26
28
 
27
29
  test "is length is true" do
28
- validation = Validatable::ValidatesLengthOf.new :username
29
- validation.is = 2
30
+ validation = Validatable::ValidatesLengthOf.new :username, :is => 2
30
31
  instance = stub(:username=>"uu")
31
32
  assert_equal true, validation.valid?(instance)
32
33
  end
33
34
 
34
- test "valid length" do
35
- validation = Validatable::ValidatesLengthOf.new :username
36
- validation.minimum = 2
37
- validation.maximum = 8
38
- instance = stub(:username=>"udfgdf")
35
+ test "within lower bound is true" do
36
+ validation = Validatable::ValidatesLengthOf.new :username, :within => 2..4
37
+ instance = stub(:username => "aa")
39
38
  assert_equal true, validation.valid?(instance)
40
39
  end
41
-
40
+
41
+ test "within outside lower bound is false" do
42
+ validation = Validatable::ValidatesLengthOf.new :username, :within => 2..4
43
+ instance = stub(:username => "a")
44
+ assert_equal false, validation.valid?(instance)
45
+ end
46
+
47
+ test "within upper bound is true" do
48
+ validation = Validatable::ValidatesLengthOf.new :username, :within => 2..4
49
+ instance = stub(:username => "aaaa")
50
+ assert_equal true, validation.valid?(instance)
51
+ end
52
+
53
+ test "within outside upper bound is false" do
54
+ validation = Validatable::ValidatesLengthOf.new :username, :within => 2..4
55
+ instance = stub(:username => "aaaaa")
56
+ assert_equal false, validation.valid?(instance)
57
+ end
58
+
42
59
  expect true do
43
- options = {:message => nil, :if => nil, :times => nil, :level => nil, :groups => nil, :maximum => nil, :minimum => nil, :is => nil}
44
- Validatable::ValidatesLengthOf.must_understand(options)
60
+ options = [:message, :if, :times, :level, :groups, :maximum, :minimum, :is, :within]
61
+ Validatable::ValidatesLengthOf.new(:test).must_understand(options.to_blank_options_hash)
45
62
  end
46
63
 
47
64
  end
@@ -21,6 +21,18 @@ module Unit
21
21
  assert_equal true, validation.valid?(instance)
22
22
  end
23
23
 
24
+ test "when value is a decimal but only_integer is true, then valid is false" do
25
+ validation = Validatable::ValidatesNumericalityOf.new :some_decimal, :only_integer => true
26
+ instance = stub(:some_decimal => 1.23)
27
+ assert_equal false, validation.valid?(instance)
28
+ end
29
+
30
+ test "when value is an integer string and only_integer is true, then valid is true" do
31
+ validation = Validatable::ValidatesNumericalityOf.new :some_negative_number, :only_integer => true
32
+ instance = stub(:some_negative_number => "-1")
33
+ assert_equal true, validation.valid?(instance)
34
+ end
35
+
24
36
  test "when value has non numeric characters then valid is false" do
25
37
  validation = Validatable::ValidatesNumericalityOf.new :some_non_numeric
26
38
  instance = stub(:some_non_numeric => "50F")
@@ -34,7 +46,8 @@ module Unit
34
46
  end
35
47
 
36
48
  expect true do
37
- Validatable::ValidatesNumericalityOf.must_understand(:message => nil, :if => nil, :times => nil, :level => nil, :groups => nil)
49
+ options = [:message, :if, :times, :level, :groups, :only_integer]
50
+ Validatable::ValidatesNumericalityOf.new(:test).must_understand(options.to_blank_options_hash)
38
51
  end
39
52
 
40
53
  end
@@ -17,7 +17,7 @@ class ValidatesPresenceOfTest < Test::Unit::TestCase
17
17
  end
18
18
 
19
19
  expect true do
20
- Validatable::ValidatesPresenceOf.must_understand(:message => nil, :if => nil, :times => nil, :level => nil, :groups => nil)
20
+ Validatable::ValidatesPresenceOf.new(:test).must_understand(:message => nil, :if => nil, :times => nil, :level => nil, :groups => nil)
21
21
  end
22
22
 
23
23
  end
@@ -2,19 +2,29 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
2
 
3
3
  class ValidatesTrueForTest < Test::Unit::TestCase
4
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 }
5
+ validation = Validatable::ValidatesTrueFor.new :name, :logic => lambda { false }
7
6
  assert_equal false, validation.valid?(stub_everything)
8
7
  end
9
8
 
10
9
  test "when block returns true for attribute value, then valid is false" do
11
- validation = Validatable::ValidatesTrueFor.new :name
12
- validation.logic = lambda { true }
10
+ validation = Validatable::ValidatesTrueFor.new :name, :logic => lambda { true }
13
11
  assert_equal true, validation.valid?(stub_everything)
14
12
  end
15
13
 
14
+ test "when no logic is given, then an error is raised during construction" do
15
+ assert_raises ArgumentError do
16
+ validation = Validatable::ValidatesTrueFor.new :age
17
+ end
18
+ end
19
+
20
+ expect true do
21
+ options = [:message, :if, :times, :level, :groups, :logic]
22
+ Validatable::ValidatesTrueFor.new(:name, options.to_blank_options_hash).must_understand(options.to_blank_options_hash)
23
+ end
24
+
16
25
  expect true do
17
- Validatable::ValidatesTrueFor.must_understand(:message => nil, :if => nil, :times => nil, :level => nil, :groups => nil, :logic => nil)
26
+ options = [:logic]
27
+ Validatable::ValidatesTrueFor.new(:name, options.to_blank_options_hash).requires(options.to_blank_options_hash)
18
28
  end
19
29
 
20
30
  end
@@ -35,12 +35,12 @@ class ValidationBaseTest < Test::Unit::TestCase
35
35
 
36
36
  test "invalid option causes raise" do
37
37
  assert_raises ArgumentError do
38
- Validatable::ValidationBase.must_understand(:foo => 1, :bar => 2)
38
+ Validatable::ValidationBase.new(:base).must_understand(:foo => 1, :bar => 2)
39
39
  end
40
40
  end
41
41
 
42
42
  expect true do
43
- Validatable::ValidationBase.must_understand(:message => nil, :if => nil, :times => nil, :level => nil, :groups => nil)
43
+ Validatable::ValidationBase.new(:base).must_understand(:message => nil, :if => nil, :times => nil, :level => nil, :groups => nil)
44
44
  end
45
45
 
46
46
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: validatable
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.2.2
7
- date: 2007-04-27 00:00:00 -04:00
6
+ version: 1.3.0
7
+ date: 2007-05-02 00:00:00 -04:00
8
8
  summary: Validatable is a library for adding validations.
9
9
  require_paths:
10
10
  - lib
@@ -30,10 +30,14 @@ authors:
30
30
  files:
31
31
  - lib/child_validation.rb
32
32
  - lib/errors.rb
33
+ - lib/requireable.rb
33
34
  - lib/understandable.rb
34
35
  - lib/validatable.rb
36
+ - lib/validatable_assertions.rb
35
37
  - lib/validatable_class_methods.rb
36
38
  - lib/validatable_instance_methods.rb
39
+ - lib/validation_assertion.rb
40
+ - lib/validation_assertion_collector.rb
37
41
  - lib/validations/validates_acceptance_of.rb
38
42
  - lib/validations/validates_confirmation_of.rb
39
43
  - lib/validations/validates_format_of.rb
@@ -44,6 +48,7 @@ files:
44
48
  - lib/validations/validation_base.rb
45
49
  - test/all_tests.rb
46
50
  - test/test_helper.rb
51
+ - test/functional/validatable_assertions_test.rb
47
52
  - test/functional/validatable_test.rb
48
53
  - test/functional/validates_acceptance_of_test.rb
49
54
  - test/functional/validates_confirmation_of_test.rb
@@ -52,7 +57,9 @@ files:
52
57
  - test/functional/validates_numericality_of_test.rb
53
58
  - test/functional/validates_presence_of_test.rb
54
59
  - test/functional/validates_true_for_test.rb
60
+ - test/functional/validation_assertion_collector_test.rb
55
61
  - test/unit/errors_test.rb
62
+ - test/unit/understandable_test.rb
56
63
  - test/unit/validatable_test.rb
57
64
  - test/unit/validates_acceptance_of_test.rb
58
65
  - test/unit/validates_confirmation_of_test.rb