File: validatable_instance_methods.rb

package info (click to toggle)
ruby-validatable 1.6.7-11
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 284 kB
  • sloc: ruby: 1,636; makefile: 10
file content (106 lines) | stat: -rw-r--r-- 3,622 bytes parent folder | download | duplicates (6)
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