validatable 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -25,10 +25,16 @@ module Validatable
25
25
  self
26
26
  end
27
27
 
28
+ # call-seq: replace(attribute)
29
+ #
30
+ # * Replaces the errors value for the given +attribute+
28
31
  def replace(attribute, value)
29
32
  errors[attribute.to_sym] = value
30
33
  end
31
34
 
35
+ # call-seq: raw(attribute)
36
+ #
37
+ # * Returns an array of error messages associated with the specified +attribute+.
32
38
  def raw(attribute)
33
39
  errors[attribute.to_sym]
34
40
  end
@@ -0,0 +1,200 @@
1
+ module Validatable
2
+ module Macros
3
+ # call-seq: validates_format_of(*args)
4
+ #
5
+ # Validates whether the value of the specified attribute is of the
6
+ # correct form by matching it against the regular expression provided.
7
+ #
8
+ # class Person
9
+ # include Validatable
10
+ # validates_format_of :first_name, :with => /[ A-Za-z]/
11
+ # end
12
+ #
13
+ # A regular expression must be provided or else an exception will be raised.
14
+ #
15
+ # Configuration options:
16
+ #
17
+ # * message - The message to add to the errors collection when the validation fails
18
+ # * times - The number of times the validation applies
19
+ # * level - The level at which the validation should occur
20
+ # * if - A block that when executed must return true of the validation will not occur
21
+ # * with - The regular expression used to validate the format
22
+ # * group - The group that this validation belongs to. A validation can belong to multiple groups
23
+ def validates_format_of(*args)
24
+ add_validations(args, ValidatesFormatOf)
25
+ end
26
+
27
+ # call-seq: validates_length_of(*args)
28
+ #
29
+ # Validates that the specified attribute matches the length restrictions supplied.
30
+ #
31
+ # class Person
32
+ # include Validatable
33
+ # validates_length_of :first_name, :maximum=>30
34
+ # validates_length_of :last_name, :minimum=>30
35
+ # end
36
+ #
37
+ # Configuration options:
38
+ #
39
+ # * message - The message to add to the errors collection when the validation fails
40
+ # * times - The number of times the validation applies
41
+ # * level - The level at which the validation should occur
42
+ # * if - A block that when executed must return true of the validation will not occur
43
+ # * minimum - The minimum size of the attribute
44
+ # * maximum - The maximum size of the attribute
45
+ # * is - The size the attribute must be
46
+ # * within - A range that the size of the attribute must fall within
47
+ # * group - The group that this validation belongs to. A validation can belong to multiple groups
48
+ def validates_length_of(*args)
49
+ add_validations(args, ValidatesLengthOf)
50
+ end
51
+
52
+ # call-seq: validates_numericality_of(*args)
53
+ #
54
+ # Validates that the specified attribute is numeric.
55
+ #
56
+ # class Person
57
+ # include Validatable
58
+ # validates_numericality_of :age
59
+ # end
60
+ #
61
+ # Configuration options:
62
+ #
63
+ # * message - The message to add to the errors collection when the validation fails
64
+ # * times - The number of times the validation applies
65
+ # * level - The level at which the validation should occur
66
+ # * if - A block that when executed must return true of the validation will not occur
67
+ # * group - The group that this validation belongs to. A validation can belong to multiple groups
68
+ # * only_integer - Whether the attribute must be an integer (default is false)
69
+ def validates_numericality_of(*args)
70
+ add_validations(args, ValidatesNumericalityOf)
71
+ end
72
+
73
+ # call-seq: validates_acceptance_of(*args)
74
+ #
75
+ # Encapsulates the pattern of wanting to validate the acceptance of a terms of service check box (or similar agreement). Example:
76
+ #
77
+ # class Person
78
+ # include Validatable
79
+ # validates_acceptance_of :terms_of_service
80
+ # validates_acceptance_of :eula, :message => "must be abided"
81
+ # end
82
+ #
83
+ # Configuration options:
84
+ #
85
+ # * message - The message to add to the errors collection when the validation fails
86
+ # * times - The number of times the validation applies
87
+ # * level - The level at which the validation should occur
88
+ # * if - A block that when executed must return true of the validation will not occur
89
+ # * group - The group that this validation belongs to. A validation can belong to multiple groups
90
+ def validates_acceptance_of(*args)
91
+ add_validations(args, ValidatesAcceptanceOf)
92
+ end
93
+
94
+ # call-seq: validates_confirmation_of(*args)
95
+ #
96
+ # Encapsulates the pattern of wanting to validate a password or email address field with a confirmation. Example:
97
+ #
98
+ # Class:
99
+ # class PersonPresenter
100
+ # include Validatable
101
+ # validates_confirmation_of :user_name, :password
102
+ # validates_confirmation_of :email_address, :message => "should match confirmation"
103
+ # end
104
+ #
105
+ # View:
106
+ # <%= password_field "person", "password" %>
107
+ # <%= password_field "person", "password_confirmation" %>
108
+ #
109
+ # Configuration options:
110
+ #
111
+ # * case_sensitive - Whether or not to apply case-sensitivity on the comparison. Defaults to true.
112
+ # * message - The message to add to the errors collection when the validation fails
113
+ # * times - The number of times the validation applies
114
+ # * level - The level at which the validation should occur
115
+ # * if - A block that when executed must return true of the validation will not occur
116
+ # * group - The group that this validation belongs to. A validation can belong to multiple groups
117
+ def validates_confirmation_of(*args)
118
+ add_validations(args, ValidatesConfirmationOf)
119
+ end
120
+
121
+ # call-seq: validates_presence_of(*args)
122
+ #
123
+ # Validates that the specified attributes are not nil or an empty string
124
+ #
125
+ # class Person
126
+ # include Validatable
127
+ # validates_presence_of :first_name
128
+ # end
129
+ #
130
+ # The first_name attribute must be in the object and it cannot be nil or empty.
131
+ #
132
+ # Configuration options:
133
+ #
134
+ # * message - The message to add to the errors collection when the validation fails
135
+ # * times - The number of times the validation applies
136
+ # * level - The level at which the validation should occur
137
+ # * if - A block that when executed must return true of the validation will not occur
138
+ # * group - The group that this validation belongs to. A validation can belong to multiple groups
139
+ def validates_presence_of(*args)
140
+ add_validations(args, ValidatesPresenceOf)
141
+ end
142
+
143
+ # call-seq: validates_true_for(*args)
144
+ #
145
+ # Validates that the logic evaluates to true
146
+ #
147
+ # class Person
148
+ # include Validatable
149
+ # validates_true_for :first_name, :logic => lambda { first_name == 'Jamie' }
150
+ # end
151
+ #
152
+ # The logic option is required.
153
+ #
154
+ # Configuration options:
155
+ #
156
+ # * message - The message to add to the errors collection when the validation fails
157
+ # * times - The number of times the validation applies
158
+ # * level - The level at which the validation should occur
159
+ # * if - A block that when executed must return true of the validation will not occur
160
+ # * group - The group that this validation belongs to. A validation can belong to multiple groups
161
+ # * logic - A block that executes to perform the validation
162
+ def validates_true_for(*args)
163
+ add_validations(args, ValidatesTrueFor)
164
+ end
165
+
166
+ # call-seq: include_validations_for(attribute_to_validate, options = {})
167
+ #
168
+ # Validates the specified attributes.
169
+ # class Person
170
+ # include Validatable
171
+ # validates_presence_of :name
172
+ # attr_accessor :name
173
+ # end
174
+ #
175
+ # class PersonPresenter
176
+ # include Validatable
177
+ # include_validations_for :person, :map => { :name => :namen }, :if => lambda { not person.nil? }
178
+ # attr_accessor :person
179
+ #
180
+ # def initialize(person)
181
+ # @person = person
182
+ # end
183
+ # end
184
+ #
185
+ # presenter = PersonPresenter.new(Person.new)
186
+ # presenter.valid? #=> false
187
+ # presenter.errors.on(:namen) #=> "can't be blank"
188
+ #
189
+ # The person attribute will be validated.
190
+ # If person is invalid the errors will be added to the PersonPresenter errors collection.
191
+ #
192
+ # Configuration options:
193
+ #
194
+ # * map - A hash that maps attributes of the child to attributes of the parent.
195
+ # * if - A block that when executed must return true of the validation will not occur.
196
+ def include_validations_for(attribute_to_validate, options = {})
197
+ children_to_validate << ChildValidation.new(attribute_to_validate, options[:map] || {}, options[:if] || lambda { true })
198
+ end
199
+ end
200
+ end
@@ -1,6 +1,6 @@
1
1
  module Validatable
2
2
  module Requireable #:nodoc:
3
- module ClassMethods
3
+ module ClassMethods #:nodoc:
4
4
  def requires(*args)
5
5
  required_options.concat args
6
6
  end
@@ -1,6 +1,6 @@
1
1
  module Validatable
2
2
  module Understandable #:nodoc:
3
- module ClassMethods
3
+ module ClassMethods #:nodoc:
4
4
  def understands(*args)
5
5
  understandings.concat args
6
6
  end
@@ -1,6 +1,7 @@
1
1
  require 'forwardable'
2
2
  require File.expand_path(File.dirname(__FILE__) + '/errors')
3
3
  require File.expand_path(File.dirname(__FILE__) + '/validatable_class_methods')
4
+ require File.expand_path(File.dirname(__FILE__) + '/macros')
4
5
  require File.expand_path(File.dirname(__FILE__) + '/validatable_instance_methods')
5
6
  require File.expand_path(File.dirname(__FILE__) + '/child_validation')
6
7
  require File.expand_path(File.dirname(__FILE__) + '/understandable')
@@ -1,51 +1,74 @@
1
- module ValidatableAssertions
1
+ module Validatable
2
+ module Assertions
2
3
 
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
4
+ def create_message_for_assertion(assertion) #:nodoc:
5
+ message = "#{assertion.klass} does not contain a #{assertion.validation_type} for #{assertion.attribute}"
6
+ message += " with options #{assertion.options.inspect}" unless assertion.options == {}
7
+ message
8
+ end
8
9
 
9
- def create_backtrace
10
- backtrace = caller
11
- backtrace.shift
12
- backtrace.shift
13
- backtrace
14
- end
10
+ def create_backtrace #:nodoc:
11
+ backtrace = caller
12
+ backtrace.shift
13
+ backtrace.shift
14
+ backtrace
15
+ end
15
16
 
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
17
+ def validation_matching_proc(assertion) #:nodoc:
18
+ lambda do |validation|
19
+ result = assertion.validation_type === validation
20
+ result &&= assertion.attribute == validation.attribute
21
+ assertion.options.each_pair do |key, value|
22
+ validation_value = validation.send key if validation.respond_to? key
23
+ result = false if validation_value.nil?
24
+ result &&= validation_value == value
25
+ end
26
+ result
24
27
  end
25
- result
26
28
  end
27
- end
28
29
 
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
30
+ def self.included(klass) #:nodoc:
31
+ Test::Unit::TestCase.class_eval do
32
+ def self.create_test_name(assertion) #:nodoc:
33
+ "test#{assertion.validation_type.to_s.gsub(/Validatable::/,'').gsub(/([A-Z])/, '_\1').downcase}_#{assertion.attribute}"
34
+ end
34
35
 
35
- def self.define_test_method name, &block
36
- class_eval do
37
- define_method name, &block
36
+ def self.define_test_method name, &block #:nodoc:
37
+ class_eval do
38
+ define_method name, &block
39
+ end
38
40
  end
39
41
  end
40
- end
41
42
 
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?
43
+ Class.class_eval do
44
+ # call-seq: must_validate
45
+ #
46
+ # class FooTest < Test::Unit::TestCase
47
+ # include Validatable::Assertions
48
+ #
49
+ # Foo.must_validate do
50
+ # presence_of :name
51
+ # format_of(:name).with(/^[A-Z]/)
52
+ # numericality_of(:age).only_integer(true)
53
+ # end
54
+ # end
55
+ #
56
+ # The above code creates a test for each line in the block given to must_validate.
57
+ # If the Foo class does not contain a presence of validation for name,
58
+ # an error with the text "Foo does not contain a Validatable::ValidatesPresenceOf for name" will be raised.
59
+ #
60
+ # Clearly this solution has limitations. Any validates_true_for validation cannot be tested using
61
+ # this DSL style of testing. Furthermore, any validation that uses an :if argument cannot use this DSL,
62
+ # since those validations require an instance to eval the :if argument against. However, for validations
63
+ # that are not validates_true_for and do not rely on an :if argument, the ValidatableAssertions can
64
+ # replace various existing success and failure validation tests.
65
+ def must_validate(&block)
66
+ test_class = eval "self", block.binding
67
+ ValidationAssertionCollector.gather(self, &block).each do |assertion|
68
+ test_class.define_test_method test_class.create_test_name(assertion) do
69
+ validation = assertion.klass.validations.find &validation_matching_proc(assertion)
70
+ add_failure create_message_for_assertion(assertion), create_backtrace if validation.nil?
71
+ end
49
72
  end
50
73
  end
51
74
  end
@@ -1,201 +1,7 @@
1
1
  module Validatable
2
- module ClassMethods
3
- # call-seq: validates_format_of(*args)
4
- #
5
- # Validates whether the value of the specified attribute is of the correct form by matching it against the regular expression provided.
6
- #
7
- # class Person
8
- # include Validatable
9
- # validates_format_of :first_name, :with => /[ A-Za-z]/
10
- # end
11
- #
12
- # A regular expression must be provided or else an exception will be raised.
13
- #
14
- # Configuration options:
15
- #
16
- # * message - The message to add to the errors collection when the validation fails
17
- # * times - The number of times the validation applies
18
- # * level - The level at which the validation should occur
19
- # * if - A block that when executed must return true of the validation will not occur
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
22
- def validates_format_of(*args)
23
- add_validations(args, ValidatesFormatOf)
24
- end
25
-
26
- # call-seq: validates_length_of(*args)
27
- #
28
- # Validates that the specified attribute matches the length restrictions supplied.
29
- #
30
- # class Person
31
- # include Validatable
32
- # validates_length_of :first_name, :maximum=>30
33
- # validates_length_of :last_name, :minimum=>30
34
- # end
35
- #
36
- # Configuration options:
37
- #
38
- # * message - The message to add to the errors collection when the validation fails
39
- # * times - The number of times the validation applies
40
- # * level - The level at which the validation should occur
41
- # * if - A block that when executed must return true of the validation will not occur
42
- # * minimum - The minimum size of the attribute
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
- # * group - The group that this validation belongs to. A validation can belong to multiple groups
47
- def validates_length_of(*args)
48
- add_validations(args, ValidatesLengthOf)
49
- end
50
-
51
- # call-seq: validates_numericality_of(*args)
52
- #
53
- # Validates that the specified attribute is numeric.
54
- #
55
- # class Person
56
- # include Validatable
57
- # validates_numericality_of :age
58
- # end
59
- #
60
- # Configuration options:
61
- #
62
- # * message - The message to add to the errors collection when the validation fails
63
- # * times - The number of times the validation applies
64
- # * level - The level at which the validation should occur
65
- # * if - A block that when executed must return true of the validation will not occur
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)
68
- def validates_numericality_of(*args)
69
- add_validations(args, ValidatesNumericalityOf)
70
- end
71
-
72
- # call-seq: validates_acceptance_of(*args)
73
- #
74
- # Encapsulates the pattern of wanting to validate the acceptance of a terms of service check box (or similar agreement). Example:
75
- #
76
- # class Person
77
- # include Validatable
78
- # validates_acceptance_of :terms_of_service
79
- # validates_acceptance_of :eula, :message => "must be abided"
80
- # end
81
- #
82
- # Configuration options:
83
- #
84
- # * message - The message to add to the errors collection when the validation fails
85
- # * times - The number of times the validation applies
86
- # * level - The level at which the validation should occur
87
- # * if - A block that when executed must return true of the validation will not occur
88
- # * group - The group that this validation belongs to. A validation can belong to multiple groups
89
- def validates_acceptance_of(*args)
90
- add_validations(args, ValidatesAcceptanceOf)
91
- end
92
-
93
- # call-seq: validates_confirmation_of(*args)
94
- #
95
- # Encapsulates the pattern of wanting to validate a password or email address field with a confirmation. Example:
96
- #
97
- # Class:
98
- # class PersonPresenter
99
- # include Validatable
100
- # validates_confirmation_of :user_name, :password
101
- # validates_confirmation_of :email_address, :message => "should match confirmation"
102
- # end
103
- #
104
- # View:
105
- # <%= password_field "person", "password" %>
106
- # <%= password_field "person", "password_confirmation" %>
107
- #
108
- # Configuration options:
109
- #
110
- # * case_sensitive - Whether or not to apply case-sensitivity on the comparison. Defaults to true.
111
- # * message - The message to add to the errors collection when the validation fails
112
- # * times - The number of times the validation applies
113
- # * level - The level at which the validation should occur
114
- # * if - A block that when executed must return true of the validation will not occur
115
- # * group - The group that this validation belongs to. A validation can belong to multiple groups
116
- def validates_confirmation_of(*args)
117
- add_validations(args, ValidatesConfirmationOf)
118
- end
119
-
120
- # call-seq: validates_presence_of(*args)
121
- #
122
- # Validates that the specified attributes are not nil or an empty string
123
- #
124
- # class Person
125
- # include Validatable
126
- # validates_presence_of :first_name
127
- # end
128
- #
129
- # The first_name attribute must be in the object and it cannot be nil or empty.
130
- #
131
- # Configuration options:
132
- #
133
- # * message - The message to add to the errors collection when the validation fails
134
- # * times - The number of times the validation applies
135
- # * level - The level at which the validation should occur
136
- # * if - A block that when executed must return true of the validation will not occur
137
- # * group - The group that this validation belongs to. A validation can belong to multiple groups
138
- def validates_presence_of(*args)
139
- add_validations(args, ValidatesPresenceOf)
140
- end
141
-
142
- # call-seq: validates_true_for(*args)
143
- #
144
- # Validates that the logic evaluates to true
145
- #
146
- # class Person
147
- # include Validatable
148
- # validates_true_for :first_name, :logic => lambda { first_name == 'Jamie' }
149
- # end
150
- #
151
- # The logic option is required.
152
- #
153
- # Configuration options:
154
- #
155
- # * message - The message to add to the errors collection when the validation fails
156
- # * times - The number of times the validation applies
157
- # * level - The level at which the validation should occur
158
- # * if - A block that when executed must return true of the validation will not occur
159
- # * group - The group that this validation belongs to. A validation can belong to multiple groups
160
- # * logic - A block that executes to perform the validation
161
- def validates_true_for(*args)
162
- add_validations(args, ValidatesTrueFor)
163
- end
164
-
165
- # call-seq: include_validations_for(attribute_to_validate, options = {})
166
- #
167
- # Validates the specified attributes.
168
- # class Person
169
- # include Validatable
170
- # validates_presence_of :name
171
- # attr_accessor :name
172
- # end
173
- #
174
- # class PersonPresenter
175
- # include Validatable
176
- # include_validations_for :person, :map => { :name => :namen }, :if => lambda { not person.nil? }
177
- # attr_accessor :person
178
- #
179
- # def initialize(person)
180
- # @person = person
181
- # end
182
- # end
183
- #
184
- # presenter = PersonPresenter.new(Person.new)
185
- # presenter.valid? #=> false
186
- # presenter.errors.on(:namen) #=> "can't be blank"
187
- #
188
- # The person attribute will be validated. If person is invalid the errors will be added to the PersonPresenter errors collection.
189
- #
190
- # Configuration options:
191
- #
192
- # * map - A hash that maps attributes of the child to attributes of the parent.
193
- # * if - A block that when executed must return true of the validation will not occur.
194
- def include_validations_for(attribute_to_validate, options = {})
195
- children_to_validate << ChildValidation.new(attribute_to_validate, options[:map] || {}, options[:if] || lambda { true })
196
- end
2
+ module ClassMethods #:nodoc:
197
3
 
198
- def validate_children(instance, group) #:nodoc:
4
+ def validate_children(instance, group)
199
5
  self.children_to_validate.each do |child_validation|
200
6
  next unless child_validation.should_validate?(instance)
201
7
  child = instance.send child_validation.attribute
@@ -216,11 +22,11 @@ module Validatable
216
22
  end
217
23
  end
218
24
 
219
- def validations #:nodoc:
25
+ def validations
220
26
  @validations ||= []
221
27
  end
222
28
 
223
- def add_error(instance, attribute, msg) #:nodoc:
29
+ def add_error(instance, attribute, msg)
224
30
  instance.errors.add(attribute, msg)
225
31
  end
226
32
 
@@ -230,7 +36,7 @@ module Validatable
230
36
 
231
37
  protected
232
38
 
233
- def add_validations(args, klass) #:nodoc:
39
+ def add_validations(args, klass)
234
40
  options = args.last.is_a?(Hash) ? args.pop : {}
235
41
  args.each do |attribute|
236
42
  new_validation = klass.new self, attribute, options
@@ -239,7 +45,7 @@ module Validatable
239
45
  end
240
46
  end
241
47
 
242
- def create_valid_method_for_groups(groups) #:nodoc:
48
+ def create_valid_method_for_groups(groups)
243
49
  groups.each do |group|
244
50
  self.class_eval do
245
51
  define_method "valid_for_#{group}?".to_sym do
@@ -249,7 +55,7 @@ module Validatable
249
55
  end
250
56
  end
251
57
 
252
- def children_to_validate #:nodoc:
58
+ def children_to_validate
253
59
  @children_to_validate ||= []
254
60
  end
255
61
 
@@ -1,13 +1,14 @@
1
1
  module Validatable
2
2
  def self.included(klass) #:nodoc:
3
3
  klass.extend Validatable::ClassMethods
4
+ klass.extend Validatable::Macros
4
5
  end
5
6
 
6
7
  # call-seq: valid?
7
8
  #
8
- # Returns true if no errors were added otherwise false.
9
+ # Returns true if no errors were added otherwise false. Only executes validations that have no :groups option specified
9
10
  def valid?
10
- valid_for_group?
11
+ valid_for_group?(nil)
11
12
  end
12
13
 
13
14
  # call-seq: errors
@@ -17,22 +18,18 @@ module Validatable
17
18
  @errors ||= Validatable::Errors.new
18
19
  end
19
20
 
20
- def valid_for_group?(group=nil) #:nodoc:
21
+ def valid_for_group?(group) #:nodoc:
21
22
  errors.clear
22
23
  self.class.validate_children(self, group)
23
24
  self.validate(group)
24
25
  errors.empty?
25
26
  end
26
27
 
27
- def times_validated(key)
28
+ def times_validated(key) #:nodoc:
28
29
  times_validated_hash[key] || 0
29
30
  end
30
31
 
31
- def times_validated_hash
32
- @times_validated_hash ||= {}
33
- end
34
-
35
- def increment_times_validated_for(validation)
32
+ def increment_times_validated_for(validation) #:nodoc:
36
33
  if validation.key != nil
37
34
  if times_validated_hash[validation.key].nil?
38
35
  times_validated_hash[validation.key] = 1
@@ -43,6 +40,10 @@ module Validatable
43
40
  end
44
41
 
45
42
  protected
43
+ def times_validated_hash #:nodoc:
44
+ @times_validated_hash ||= {}
45
+ end
46
+
46
47
  def validate(group) #:nodoc:
47
48
  validation_levels.each do |level|
48
49
  validations_for_level_and_group(level, group).each do |validation|
@@ -65,7 +66,7 @@ module Validatable
65
66
 
66
67
  def validations_for_level_and_group(level, group) #:nodoc:
67
68
  validations_for_level = self.class.validations.select { |validation| validation.level == level }
68
- return validations_for_level if group.nil?
69
+ return validations_for_level.select { |validation| validation.groups.empty? } if group.nil?
69
70
  validations_for_level.select { |validation| validation.groups.include?(group) }
70
71
  end
71
72
 
@@ -1,4 +1,4 @@
1
- class ValidationAssertion
1
+ class ValidationAssertion #:nodoc:
2
2
  attr_accessor :klass, :validation_type, :options, :attribute
3
3
 
4
4
  def initialize(klass, validation_type, attribute)
@@ -1,4 +1,4 @@
1
- class ValidationAssertionCollector
1
+ class ValidationAssertionCollector #:nodoc:
2
2
  def self.gather(klass, &block)
3
3
  collector = self.new(klass)
4
4
  collector.instance_eval(&block)
@@ -12,7 +12,7 @@ class ValidationAssertionCollector
12
12
  end
13
13
  end
14
14
 
15
- Validatable::ClassMethods.public_instance_methods.sort.grep(/^validates_/).each do |validation_method|
15
+ Validatable::Macros.public_instance_methods.sort.grep(/^validates_/).each do |validation_method|
16
16
  next if validation_method == 'validates_true_for'
17
17
  validatable_class = Validatable.const_get(validation_method.split(/_/).collect { |word| word.capitalize}.join)
18
18
  define_method_for_validation_method(validation_method, validatable_class)
@@ -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.4.0"
32
+ s.version = "1.5.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'
@@ -1,23 +1,23 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
2
 
3
- class ValidatableAssertionsTest < Test::Unit::TestCase
3
+ class Validatable::AssertionsTest < Test::Unit::TestCase
4
4
  expect "Klass does not contain a ValidationType for Attribute" do
5
5
  klass = Class.new do
6
- include ValidatableAssertions
6
+ include Validatable::Assertions
7
7
  end
8
8
  klass.new.create_message_for_assertion(stub(:klass=>"Klass", :validation_type=>"ValidationType", :attribute=>"Attribute", :options=>{}))
9
9
  end
10
10
 
11
11
  expect "Klass does not contain a ValidationType for Attribute" do
12
12
  klass = Class.new do
13
- include ValidatableAssertions
13
+ include Validatable::Assertions
14
14
  end
15
15
  klass.new.create_message_for_assertion(stub(:klass=>"Klass", :validation_type=>"ValidationType", :attribute=>"Attribute", :options=>{}))
16
16
  end
17
17
 
18
18
  expect false do
19
19
  klass = Class.new do
20
- include ValidatableAssertions
20
+ include Validatable::Assertions
21
21
  end
22
22
  assertion = stub(:validation_type=>stub(:=== => true), :attribute => "attribute", :options=>{:level => 1, :times => 2})
23
23
  validation = stub(:validation_type=>"validation_type", :attribute => "attribute", :level => 2, :times => 2)
@@ -26,7 +26,7 @@ class ValidatableAssertionsTest < Test::Unit::TestCase
26
26
 
27
27
  expect false do
28
28
  klass = Class.new do
29
- include ValidatableAssertions
29
+ include Validatable::Assertions
30
30
  end
31
31
  assertion = stub(:validation_type=>stub(:=== => true), :attribute => "non matching attribute", :options=>{})
32
32
  validation = stub(:validation_type=>"validation_type", :attribute => nil)
@@ -35,7 +35,7 @@ class ValidatableAssertionsTest < Test::Unit::TestCase
35
35
 
36
36
  expect false do
37
37
  klass = Class.new do
38
- include ValidatableAssertions
38
+ include Validatable::Assertions
39
39
  end
40
40
  assertion = stub(:validation_type=>"non matching validation_type", :options=>{})
41
41
  validation = stub(:validation_type=>"validation_type")
@@ -44,7 +44,7 @@ class ValidatableAssertionsTest < Test::Unit::TestCase
44
44
 
45
45
  expect true do
46
46
  klass = Class.new do
47
- include ValidatableAssertions
47
+ include Validatable::Assertions
48
48
  end
49
49
  assertion = stub(:validation_type=>stub(:=== => true), :attribute => "attribute", :options=>{:level => 1, :times => 2})
50
50
  validation = stub(:validation_type=>"validation_type", :attribute => "attribute", :level => 1, :times => 2)
@@ -53,7 +53,7 @@ class ValidatableAssertionsTest < Test::Unit::TestCase
53
53
 
54
54
  expect true do
55
55
  Class.new do
56
- include ValidatableAssertions
56
+ include Validatable::Assertions
57
57
  end
58
58
 
59
59
  Class.respond_to? :must_validate
@@ -61,14 +61,14 @@ class ValidatableAssertionsTest < Test::Unit::TestCase
61
61
 
62
62
  expect "test_validates_presence_of_name" do
63
63
  test_class = Class.new(Test::Unit::TestCase) do
64
- include ValidatableAssertions
64
+ include Validatable::Assertions
65
65
  end
66
66
  test_class.create_test_name(stub(:validation_type=>Validatable::ValidatesPresenceOf, :attribute=>:name))
67
67
  end
68
68
 
69
69
  expect true do
70
70
  test_class = Class.new(Test::Unit::TestCase) do
71
- include ValidatableAssertions
71
+ include Validatable::Assertions
72
72
  end
73
73
 
74
74
  test_class.define_test_method :some_test do
@@ -83,7 +83,7 @@ class ValidatableAssertionsTest < Test::Unit::TestCase
83
83
  include Validatable
84
84
  end
85
85
  test_class = Class.new Test::Unit::TestCase do
86
- include ValidatableAssertions
86
+ include Validatable::Assertions
87
87
 
88
88
  klass.must_validate do
89
89
  presence_of :anything
@@ -1,7 +1,7 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
2
 
3
3
  module Functional
4
- class ValidatableTest < Test::Unit::TestCase
4
+ class ValidatableTest < Test::Unit::TestCase
5
5
 
6
6
  expect ArgumentError do
7
7
  Class.new do
@@ -227,7 +227,19 @@ module Functional
227
227
  instance.valid_for_group_one?
228
228
  end
229
229
 
230
- expect false do
230
+ expect true do
231
+ klass = Class.new do
232
+ include Validatable
233
+ validates_presence_of :name, :groups => :group_one
234
+ validates_presence_of :address
235
+ attr_accessor :name, :address
236
+ end
237
+ instance = klass.new
238
+ instance.address = 'anything'
239
+ instance.valid?
240
+ end
241
+
242
+ expect true do
231
243
  klass = Class.new do
232
244
  include Validatable
233
245
  validates_presence_of :name, :groups => :group_one
@@ -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_everything(:valid? => false, :should_validate? => true, :attribute => "attribute", :level => 1)
6
+ validation = stub_everything(:should_validate? => true, :attribute => "attribute", :level => 1, :groups => [])
7
7
  klass = Class.new do
8
8
  include Validatable
9
9
  validations << validation
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: validatable
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.4.0
7
- date: 2007-06-02 00:00:00 -04:00
6
+ version: 1.5.0
7
+ date: 2007-06-19 00:00:00 -04:00
8
8
  summary: Validatable is a library for adding validations.
9
9
  require_paths:
10
10
  - lib
@@ -31,6 +31,7 @@ authors:
31
31
  files:
32
32
  - lib/child_validation.rb
33
33
  - lib/errors.rb
34
+ - lib/macros.rb
34
35
  - lib/requireable.rb
35
36
  - lib/understandable.rb
36
37
  - lib/validatable.rb