mongomatic 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. data/README.rdoc +90 -26
  2. data/lib/mongomatic/base.rb +20 -11
  3. data/lib/mongomatic/errors.rb +7 -0
  4. data/lib/mongomatic.rb +1 -2
  5. data/test/helper.rb +4 -1
  6. data/test/test_mongomatic.rb +3 -3
  7. metadata +13 -25
  8. data/lib/mongomatic/validatable/child_validation.rb +0 -17
  9. data/lib/mongomatic/validatable/errors.rb +0 -108
  10. data/lib/mongomatic/validatable/included_validation.rb +0 -11
  11. data/lib/mongomatic/validatable/macros.rb +0 -316
  12. data/lib/mongomatic/validatable/object_extension.rb +0 -21
  13. data/lib/mongomatic/validatable/requireable.rb +0 -28
  14. data/lib/mongomatic/validatable/understandable.rb +0 -33
  15. data/lib/mongomatic/validatable/validatable_class_methods.rb +0 -89
  16. data/lib/mongomatic/validatable/validatable_instance_methods.rb +0 -111
  17. data/lib/mongomatic/validatable/validations/validates_acceptance_of.rb +0 -16
  18. data/lib/mongomatic/validatable/validations/validates_associated.rb +0 -15
  19. data/lib/mongomatic/validatable/validations/validates_confirmation_of.rb +0 -25
  20. data/lib/mongomatic/validatable/validations/validates_each.rb +0 -16
  21. data/lib/mongomatic/validatable/validations/validates_exclusion_of.rb +0 -19
  22. data/lib/mongomatic/validatable/validations/validates_format_of.rb +0 -18
  23. data/lib/mongomatic/validatable/validations/validates_inclusion_of.rb +0 -19
  24. data/lib/mongomatic/validatable/validations/validates_length_of.rb +0 -32
  25. data/lib/mongomatic/validatable/validations/validates_numericality_of.rb +0 -28
  26. data/lib/mongomatic/validatable/validations/validates_presence_of.rb +0 -18
  27. data/lib/mongomatic/validatable/validations/validates_true_for.rb +0 -15
  28. data/lib/mongomatic/validatable/validations/validation_base.rb +0 -93
  29. data/lib/mongomatic/validatable.rb +0 -31
@@ -1,316 +0,0 @@
1
- module Mongomatic
2
- module Validatable
3
- module Macros
4
- # call-seq: validates_each(*args)
5
- #
6
- # Validates that the logic evaluates to true
7
- #
8
- # class Address
9
- # include Validatable
10
- # validates_each :zip_code, :logic => lambda { errors.add(:zip_code, "is not valid") if ZipCodeService.allows(zip_code) }
11
- # end
12
- #
13
- # The logic option is required.
14
- #
15
- # Configuration options:
16
- #
17
- # * after_validate - A block that executes following the run of a validation
18
- # * group - The group that this validation belongs to. A validation can belong to multiple groups
19
- # * if - A block that when executed must return true of the validation will not occur
20
- # * level - The level at which the validation should occur
21
- # * logic - A block that executes to perform the validation
22
- # * message - The message to add to the errors collection when the validation fails
23
- # * times - The number of times the validation applies
24
- def validates_each(*args)
25
- add_validations(args, ValidatesEach)
26
- end
27
-
28
- # call-seq: validates_format_of(*args)
29
- #
30
- # Validates whether the value of the specified attribute is of the
31
- # correct form by matching it against the regular expression provided.
32
- #
33
- # class Person
34
- # include Validatable
35
- # validates_format_of :first_name, :with => /[ A-Za-z]/
36
- # end
37
- #
38
- # A regular expression must be provided or else an exception will be raised.
39
- #
40
- # Configuration options:
41
- #
42
- # * after_validate - A block that executes following the run of a validation
43
- # * message - The message to add to the errors collection when the validation fails
44
- # * times - The number of times the validation applies
45
- # * level - The level at which the validation should occur
46
- # * if - A block that when executed must return true of the validation will not occur
47
- # * with - The regular expression used to validate the format
48
- # * group - The group that this validation belongs to. A validation can belong to multiple groups
49
- def validates_format_of(*args)
50
- add_validations(args, ValidatesFormatOf)
51
- end
52
-
53
- # call-seq: validates_length_of(*args)
54
- #
55
- # Validates that the specified attribute matches the length restrictions supplied.
56
- #
57
- # class Person
58
- # include Validatable
59
- # validates_length_of :first_name, :maximum=>30
60
- # validates_length_of :last_name, :minimum=>30
61
- # end
62
- #
63
- # Configuration options:
64
- #
65
- # * after_validate - A block that executes following the run of a validation
66
- # * message - The message to add to the errors collection when the validation fails
67
- # * times - The number of times the validation applies
68
- # * level - The level at which the validation should occur
69
- # * if - A block that when executed must return true of the validation will not occur
70
- # * minimum - The minimum size of the attribute
71
- # * maximum - The maximum size of the attribute
72
- # * is - The size the attribute must be
73
- # * within - A range that the size of the attribute must fall within
74
- # * group - The group that this validation belongs to. A validation can belong to multiple groups
75
- def validates_length_of(*args)
76
- add_validations(args, ValidatesLengthOf)
77
- end
78
-
79
- # call-seq: validates_numericality_of(*args)
80
- #
81
- # Validates that the specified attribute is numeric.
82
- #
83
- # class Person
84
- # include Validatable
85
- # validates_numericality_of :age
86
- # end
87
- #
88
- # Configuration options:
89
- #
90
- # * after_validate - A block that executes following the run of a validation
91
- # * message - The message to add to the errors collection when the validation fails
92
- # * times - The number of times the validation applies
93
- # * level - The level at which the validation should occur
94
- # * if - A block that when executed must return true of the validation will not occur
95
- # * group - The group that this validation belongs to. A validation can belong to multiple groups
96
- # * only_integer - Whether the attribute must be an integer (default is false)
97
- def validates_numericality_of(*args)
98
- add_validations(args, ValidatesNumericalityOf)
99
- end
100
-
101
- # call-seq: validates_acceptance_of(*args)
102
- #
103
- # Encapsulates the pattern of wanting to validate the acceptance of a terms of service check box (or similar agreement). Example:
104
- #
105
- # class Person
106
- # include Validatable
107
- # validates_acceptance_of :terms_of_service
108
- # validates_acceptance_of :eula, :message => "must be abided"
109
- # end
110
- #
111
- # Configuration options:
112
- #
113
- # * after_validate - A block that executes following the run of a validation
114
- # * message - The message to add to the errors collection when the validation fails
115
- # * times - The number of times the validation applies
116
- # * level - The level at which the validation should occur
117
- # * if - A block that when executed must return true of the validation will not occur
118
- # * group - The group that this validation belongs to. A validation can belong to multiple groups
119
- def validates_acceptance_of(*args)
120
- add_validations(args, ValidatesAcceptanceOf)
121
- end
122
-
123
- # call-seq: validates_confirmation_of(*args)
124
- #
125
- # Encapsulates the pattern of wanting to validate a password or email address field with a confirmation. Example:
126
- #
127
- # Class:
128
- # class PersonPresenter
129
- # include Validatable
130
- # validates_confirmation_of :user_name, :password
131
- # validates_confirmation_of :email_address, :message => "should match confirmation"
132
- # end
133
- #
134
- # View:
135
- # <%= password_field "person", "password" %>
136
- # <%= password_field "person", "password_confirmation" %>
137
- #
138
- # Configuration options:
139
- #
140
- # * after_validate - A block that executes following the run of a validation
141
- # * case_sensitive - Whether or not to apply case-sensitivity on the comparison. Defaults to true.
142
- # * message - The message to add to the errors collection when the validation fails
143
- # * times - The number of times the validation applies
144
- # * level - The level at which the validation should occur
145
- # * if - A block that when executed must return true of the validation will not occur
146
- # * group - The group that this validation belongs to. A validation can belong to multiple groups
147
- def validates_confirmation_of(*args)
148
- add_validations(args, ValidatesConfirmationOf)
149
- end
150
-
151
- # call-seq: validates_presence_of(*args)
152
- #
153
- # Validates that the specified attributes are not nil or an empty string
154
- #
155
- # class Person
156
- # include Validatable
157
- # validates_presence_of :first_name
158
- # end
159
- #
160
- # The first_name attribute must be in the object and it cannot be nil or empty.
161
- #
162
- # Configuration options:
163
- #
164
- # * after_validate - A block that executes following the run of a validation
165
- # * message - The message to add to the errors collection when the validation fails
166
- # * times - The number of times the validation applies
167
- # * level - The level at which the validation should occur
168
- # * if - A block that when executed must return true of the validation will not occur
169
- # * group - The group that this validation belongs to. A validation can belong to multiple groups
170
- def validates_presence_of(*args)
171
- add_validations(args, ValidatesPresenceOf)
172
- end
173
-
174
- # call-seq: validates_true_for(*args)
175
- #
176
- # Validates that the logic evaluates to true
177
- #
178
- # class Person
179
- # include Validatable
180
- # validates_true_for :first_name, :logic => lambda { first_name == 'Jamie' }
181
- # end
182
- #
183
- # The logic option is required.
184
- #
185
- # Configuration options:
186
- #
187
- # * after_validate - A block that executes following the run of a validation
188
- # * message - The message to add to the errors collection when the validation fails
189
- # * times - The number of times the validation applies
190
- # * level - The level at which the validation should occur
191
- # * if - A block that when executed must return true of the validation will not occur
192
- # * group - The group that this validation belongs to. A validation can belong to multiple groups
193
- # * logic - A block that executes to perform the validation
194
- def validates_true_for(*args)
195
- add_validations(args, ValidatesTrueFor)
196
- end
197
-
198
- def validates_exclusion_of(*args)
199
- add_validations(args, ValidatesExclusionOf)
200
- end
201
-
202
- def validates_inclusion_of(*args)
203
- add_validations(args, ValidatesInclusionOf)
204
- end
205
-
206
- # call-seq: validates_associated(*args)
207
- #
208
- # Checks the validity of an associated object or objects and adds a single
209
- # error if validation fails.
210
- #
211
- # class Person
212
- # include Validatable
213
- # attr_accessor :addresses
214
- # validates_associated :addresses
215
- # end
216
- #
217
- # Configuration options:
218
- #
219
- # * after_validate - A block that executes following the run of a validation
220
- # * message - The message to add to the errors collection when the validation fails
221
- # * times - The number of times the validation applies
222
- # * level - The level at which the validation should occur
223
- # * if - A block that when executed must return true of the validation will not occur
224
- # * group - The group that this validation belongs to. A validation can belong to multiple groups
225
- def validates_associated(*args)
226
- add_validations(args, ValidatesAssociated)
227
- end
228
-
229
- # call-seq: include_validations_from(attribute)
230
- #
231
- # Includes all the validations that are defined on the attribute.
232
- # class Person
233
- # include Validatable
234
- # validates_presence_of :name
235
- # end
236
- #
237
- # class PersonPresenter
238
- # include Validatable
239
- # include_validataions_from :person
240
- # attr_accessor :person
241
- # def name
242
- # person.name
243
- # end
244
- #
245
- # def initialize(person)
246
- # @person = person
247
- # end
248
- # end
249
- #
250
- # presenter = PersonPresenter.new(Person.new)
251
- # presenter.valid? #=> false
252
- # presenter.errors.on(:name) #=> "can't be blank"
253
- #
254
- # The name attribute whose validations should be added.
255
- def include_validations_from(attribute_to_validate, options = {})
256
- validations_to_include << IncludedValidation.new(attribute_to_validate)
257
- end
258
-
259
- # call-seq: include_errors_from(attribute_to_validate, options = {})
260
- #
261
- # Validates the specified attributes.
262
- # class Person
263
- # include Validatable
264
- # validates_presence_of :name
265
- # attr_accessor :name
266
- # end
267
- #
268
- # class PersonPresenter
269
- # include Validatable
270
- # include_errors_from :person, :map => { :name => :namen }, :if => lambda { not person.nil? }
271
- # attr_accessor :person
272
- #
273
- # def initialize(person)
274
- # @person = person
275
- # end
276
- # end
277
- #
278
- # presenter = PersonPresenter.new(Person.new)
279
- # presenter.valid? #=> false
280
- # presenter.errors.on(:namen) #=> "can't be blank"
281
- #
282
- # The person attribute will be validated.
283
- # If person is invalid the errors will be added to the PersonPresenter errors collection.
284
- #
285
- # Configuration options:
286
- #
287
- # * map - A hash that maps attributes of the child to attributes of the parent.
288
- # * if - A block that when executed must return true of the validation will not occur.
289
- def include_errors_from(attribute_to_validate, options = {})
290
- children_to_validate << ChildValidation.new(attribute_to_validate, options[:map] || {}, options[:if] || lambda { true })
291
- end
292
-
293
- def include_validations_for(attribute_to_validate, options = {}) #:nodoc:
294
- puts "include_validations_for is deprecated; use include_errors_from instead"
295
- children_to_validate << ChildValidation.new(attribute_to_validate, options[:map] || {}, options[:if] || lambda { true })
296
- end
297
-
298
- # call-seq: before_validation(&block)
299
- #
300
- # Is called before valid? or valid_for_*?
301
- #
302
- # class Person
303
- # include Validatable
304
- # before_validation do
305
- # self.name = "default name"
306
- # end
307
- #
308
- # attr_accessor :name
309
- # end
310
- #
311
- def before_validation(&block)
312
- before_validations << block
313
- end
314
- end
315
- end
316
- end
@@ -1,21 +0,0 @@
1
- class Object #:nodoc:
2
- module InstanceExecHelper #:nodoc:
3
- end
4
- include InstanceExecHelper
5
- def instance_eval_with_params(*args, &block)
6
- begin
7
- old_critical, Thread.critical = Thread.critical, true
8
- n = 0
9
- n += 1 while respond_to?(mname="__instance_exec#{n}")
10
- InstanceExecHelper.module_eval{ define_method(mname, &block) }
11
- ensure
12
- Thread.critical = old_critical
13
- end
14
- begin
15
- ret = send(mname, *args)
16
- ensure
17
- InstanceExecHelper.module_eval{ remove_method(mname) } rescue nil
18
- end
19
- ret
20
- end
21
- end
@@ -1,28 +0,0 @@
1
- module Mongomatic
2
- module Validatable
3
- module Requireable #:nodoc:
4
- module ClassMethods #:nodoc:
5
- def requires(*args)
6
- required_options.concat args
7
- end
8
-
9
- def required_options
10
- @required_options ||= []
11
- end
12
- end
13
-
14
- def self.included(klass)
15
- klass.extend ClassMethods
16
- end
17
-
18
- def requires(options)
19
- required_options = self.class.required_options.inject([]) do |errors, attribute|
20
- errors << attribute.to_s unless options.has_key?(attribute)
21
- errors
22
- end
23
- raise ArgumentError.new("#{self.class} requires options: #{required_options.join(', ')}") if required_options.any?
24
- true
25
- end
26
- end
27
- end
28
- end
@@ -1,33 +0,0 @@
1
- module Mongomatic
2
- module Validatable
3
- module Understandable #:nodoc:
4
- module ClassMethods #:nodoc:
5
- def understands(*args)
6
- understandings.concat args
7
- end
8
-
9
- def understandings
10
- @understandings ||= []
11
- end
12
-
13
- def all_understandings
14
- return understandings + self.superclass.all_understandings if self.superclass.respond_to? :all_understandings
15
- understandings
16
- end
17
- end
18
-
19
- def self.included(klass)
20
- klass.extend ClassMethods
21
- end
22
-
23
- def must_understand(hash)
24
- invalid_options = hash.inject([]) do |errors, (key, value)|
25
- errors << key.to_s unless self.class.all_understandings.include?(key)
26
- errors
27
- end
28
- raise ArgumentError.new("invalid options: #{invalid_options.join(', ')}") if invalid_options.any?
29
- true
30
- end
31
- end
32
- end
33
- end
@@ -1,89 +0,0 @@
1
- module Mongomatic
2
- module Validatable
3
- module ClassMethods #:nodoc:
4
-
5
- def validate_children(instance, group)
6
- self.children_to_validate.each do |child_validation|
7
- next unless child_validation.should_validate?(instance)
8
- child_or_children = instance.send child_validation.attribute
9
- [child_or_children].flatten.each do |child|
10
- if (child.respond_to?(:valid_for_group?))
11
- child.valid_for_group?(group)
12
- else
13
- child.valid?
14
- end
15
- child.errors.each do |attribute, messages|
16
- if messages.is_a?(String)
17
- add_error(instance, child_validation.map[attribute.to_sym] || attribute, messages)
18
- else
19
- messages.each do |message|
20
- add_error(instance, child_validation.map[attribute.to_sym] || attribute, message)
21
- end
22
- end
23
- end
24
- end
25
- end
26
- end
27
-
28
- def all_before_validations
29
- if self.superclass.respond_to? :all_before_validations
30
- return before_validations + self.superclass.all_before_validations
31
- end
32
- before_validations
33
- end
34
-
35
- def before_validations
36
- @before_validations ||= []
37
- end
38
-
39
- def all_validations
40
- if self.respond_to?(:superclass) && self.superclass.respond_to?(:all_validations)
41
- return validations + self.superclass.all_validations
42
- end
43
- validations
44
- end
45
-
46
- def validations
47
- @validations ||= []
48
- end
49
-
50
- def add_error(instance, attribute, msg)
51
- instance.errors.add(attribute, msg)
52
- end
53
-
54
- def validation_keys_include?(key)
55
- validations.map { |validation| validation.key }.include?(key)
56
- end
57
-
58
- def validations_to_include
59
- @validations_to_include ||= []
60
- end
61
-
62
- protected
63
-
64
- def add_validations(args, klass)
65
- options = args.last.is_a?(Hash) ? args.pop : {}
66
- args.each do |attribute|
67
- new_validation = klass.new self, attribute, options
68
- self.validations << new_validation
69
- self.create_valid_method_for_groups new_validation.groups
70
- end
71
- end
72
-
73
- def create_valid_method_for_groups(groups)
74
- groups.each do |group|
75
- self.class_eval do
76
- define_method "valid_for_#{group}?".to_sym do
77
- valid_for_group?(group)
78
- end
79
- end
80
- end
81
- end
82
-
83
- def children_to_validate
84
- @children_to_validate ||= []
85
- end
86
-
87
- end
88
- end
89
- end
@@ -1,111 +0,0 @@
1
- module Mongomatic
2
- module Validatable
3
- def self.included(klass) #:nodoc:
4
- klass.extend Validatable::ClassMethods
5
- klass.extend Validatable::Macros
6
- end
7
-
8
- # call-seq: valid?
9
- #
10
- # Returns true if no errors were added otherwise false. Only executes validations that have no :groups option specified
11
- def valid?
12
- self.send(:before_validate) if self.respond_to?(:before_validate)
13
- r = valid_for_group?(nil)
14
- self.send(:after_validate) if self.respond_to?(:after_validate)
15
- r
16
- end
17
-
18
- # call-seq: errors
19
- #
20
- # Returns the Errors object that holds all information about attribute error messages.
21
- def errors
22
- @errors ||= Validatable::Errors.new
23
- end
24
-
25
- def valid_for_group?(group) #:nodoc:
26
- errors.clear
27
- run_before_validations
28
- self.class.validate_children(self, group)
29
- self.validate_group(group)
30
- errors.empty?
31
- end
32
-
33
- def times_validated(key) #:nodoc:
34
- times_validated_hash[key] || 0
35
- end
36
-
37
- def increment_times_validated_for(validation) #:nodoc:
38
- if validation.key != nil
39
- if times_validated_hash[validation.key].nil?
40
- times_validated_hash[validation.key] = 1
41
- else
42
- times_validated_hash[validation.key] += 1
43
- end
44
- end
45
- end
46
-
47
- # call-seq: validate_only(key)
48
- #
49
- # Only executes a specified validation. The argument should follow a pattern based on the key of the validation.
50
- # Examples:
51
- # * validates_presence_of :name can be run with obj.validate_only("presence_of/name")
52
- # * validates_presence_of :birthday, :key => "a key" can be run with obj.validate_only("presence_of/a key")
53
- def validate_only(key)
54
- validation_name, attribute_name = key.split("/")
55
- validation_name = validation_name.split("_").collect{|word| word.capitalize}.join
56
- validation_key = "#{self.class.name}/Validatable::Validates#{validation_name}/#{attribute_name}"
57
- validation = self.class.all_validations.find { |validation| validation.key == validation_key }
58
- raise ArgumentError.new("validation with key #{validation_key} could not be found") if validation.nil?
59
- errors.clear
60
- run_validation(validation)
61
- end
62
-
63
- protected
64
- def times_validated_hash #:nodoc:
65
- @times_validated_hash ||= {}
66
- end
67
-
68
- def validate_group(group) #:nodoc:
69
- validation_levels.each do |level|
70
- validations_for_level_and_group(level, group).each do |validation|
71
- run_validation(validation) if validation.should_validate?(self)
72
- end
73
- return unless self.errors.empty?
74
- end
75
- end
76
-
77
- def run_validation(validation) #:nodoc:
78
- validation_result = validation.valid?(self)
79
- add_error(validation.attribute, validation.message(self)) unless validation_result
80
- increment_times_validated_for(validation)
81
- validation.run_after_validate(validation_result, self, validation.attribute)
82
- end
83
-
84
- def run_before_validations #:nodoc:
85
- self.class.all_before_validations.each do |block|
86
- instance_eval &block
87
- end
88
- end
89
-
90
- def add_error(attribute, message) #:nodoc:
91
- self.class.add_error(self, attribute, message)
92
- end
93
-
94
- def validations_for_level_and_group(level, group) #:nodoc:
95
- validations_for_level = self.all_validations.select { |validation| validation.level == level }
96
- return validations_for_level.select { |validation| validation.groups.empty? } if group.nil?
97
- validations_for_level.select { |validation| validation.groups.include?(group) }
98
- end
99
-
100
- def all_validations #:nodoc:
101
- res = self.class.validations_to_include.inject(self.class.all_validations) do |result, included_validation_class|
102
- result += self.send(included_validation_class.attribute).all_validations
103
- result
104
- end
105
- end
106
-
107
- def validation_levels #:nodoc:
108
- self.class.all_validations.inject([1]) { |result, validation| result << validation.level }.uniq.sort
109
- end
110
- end
111
- end
@@ -1,16 +0,0 @@
1
- module Mongomatic
2
- module Validatable
3
- class ValidatesAcceptanceOf < ValidationBase #:nodoc:
4
- def valid?(instance)
5
- value = instance[self.attribute.to_s]
6
- return true if allow_nil && value.nil?
7
- return true if allow_blank && value.blank?
8
- %w(1 true t).include?(value)
9
- end
10
-
11
- def message(instance)
12
- super || "must be accepted"
13
- end
14
- end
15
- end
16
- end
@@ -1,15 +0,0 @@
1
- module Mongomatic
2
- module Validatable
3
- class ValidatesAssociated < ValidationBase #:nodoc:
4
- def valid?(instance)
5
- Array(instance.send(attribute)).compact.map do |child|
6
- child.valid?
7
- end.all?
8
- end
9
-
10
- def message(instance)
11
- super || "is invalid"
12
- end
13
- end
14
- end
15
- end
@@ -1,25 +0,0 @@
1
- module Mongomatic
2
- module Validatable
3
- class ValidatesConfirmationOf < ValidationBase #:nodoc:
4
- option :case_sensitive
5
- default :case_sensitive => true
6
-
7
- def initialize(klass, attribute, options={})
8
- klass.class_eval { attr_accessor "#{attribute}_confirmation" }
9
- super
10
- end
11
-
12
- def valid?(instance)
13
- confirmation_value = instance.send("#{self.attribute}_confirmation")
14
- return true if allow_nil && confirmation_value.nil?
15
- return true if allow_blank && confirmation_value.blank?
16
- return instance[self.attribute.to_s] == instance.send("#{self.attribute}_confirmation".to_sym) if case_sensitive
17
- instance[self.attribute.to_s].to_s.casecmp(instance.send("#{self.attribute}_confirmation".to_sym).to_s) == 0
18
- end
19
-
20
- def message(instance)
21
- super || "doesn't match confirmation"
22
- end
23
- end
24
- end
25
- end
@@ -1,16 +0,0 @@
1
- module Mongomatic
2
- module Validatable
3
- class ValidatesEach < ValidationBase #:nodoc:
4
- required_option :logic
5
-
6
- def valid?(instance)
7
- instance.instance_eval(&logic)
8
- true # return true so no error is added. should look in the future at doing this different.
9
- end
10
-
11
- def message(instance)
12
- super || "is invalid"
13
- end
14
- end
15
- end
16
- end