Repository navigation
Expand file tree
/
Copy pathvalidatable_instance_methods.rb
More file actions
106 lines (92 loc) · 3.54 KB
/
Copy pathvalidatable_instance_methods.rb
File metadata and controls
106 lines (92 loc) · 3.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
module Validatable
def self.included(klass) #:nodoc:
klass.extend Validatable::ClassMethods
klass.extend Validatable::Macros
end
# call-seq: valid?
#
# Returns true if no errors were added otherwise false. Only executes validations that have no :groups option specified
def valid?
valid_for_group?(nil)
end
# call-seq: errors
#
# Returns the Errors object that holds all information about attribute error messages.
def errors
@errors ||= Validatable::Errors.new
end
def valid_for_group?(group) #:nodoc:
run_before_validations
errors.clear
self.class.validate_children(self, group)
self.validate(group)
errors.empty?
end
def times_validated(key) #:nodoc:
times_validated_hash[key] || 0
end
def increment_times_validated_for(validation) #:nodoc:
if validation.key != nil
if times_validated_hash[validation.key].nil?
times_validated_hash[validation.key] = 1
else
times_validated_hash[validation.key] += 1
end
end
end
# call-seq: validate_only(key)
#
# Only executes a specified validation. The argument should follow a pattern based on the key of the validation.
# Examples:
# * validates_presence_of :name can be run with obj.validate_only("presence_of/name")
# * validates_presence_of :birthday, :key => "a key" can be run with obj.validate_only("presence_of/a key")
def validate_only(key)
validation_name, attribute_name = key.split("/")
validation_name = validation_name.split("_").collect{|word| word.capitalize}.join
validation_key = "#{self.class.name}/Validatable::Validates#{validation_name}/#{attribute_name}"
validation = self.class.all_validations.find { |validation| validation.key == validation_key }
raise ArgumentError.new("validation with key #{validation_key} could not be found") if validation.nil?
errors.clear
run_validation(validation)
end
protected
def times_validated_hash #:nodoc:
@times_validated_hash ||= {}
end
def validate(group) #:nodoc:
validation_levels.each do |level|
validations_for_level_and_group(level, group).each do |validation|
run_validation(validation) if validation.should_validate?(self)
end
return unless self.errors.empty?
end
end
def run_validation(validation) #:nodoc:
validation_result = validation.valid?(self)
add_error(validation.attribute, validation.message(self)) unless validation_result
increment_times_validated_for(validation)
validation.run_after_validate(validation_result, self, validation.attribute)
end
def run_before_validations #:nodoc:
self.class.all_before_validations.each do |block|
instance_eval &block
end
end
def add_error(attribute, message) #:nodoc:
self.class.add_error(self, attribute, message)
end
def validations_for_level_and_group(level, group) #:nodoc:
validations_for_level = self.all_validations.select { |validation| validation.level == level }
return validations_for_level.select { |validation| validation.groups.empty? } if group.nil?
validations_for_level.select { |validation| validation.groups.include?(group) }
end
def all_validations #:nodoc:
res = self.class.validations_to_include.inject(self.class.all_validations) do |result, included_validation_class|
result += self.send(included_validation_class.attribute).all_validations
result
end
end
def validation_levels #:nodoc:
self.class.all_validations.inject([1]) { |result, validation| result << validation.level }.uniq.sort
end
end