Module: Vet

Defined in:
lib/vet.rb

Class Method Summary collapse

Class Method Details

.add_vet_error(attribute, message, *opts) ⇒ Object

Add error to appropriate location in vet_errors hash



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/vet.rb', line 153

def add_vet_error(attribute, message, *opts)
  # If message includes {ATTRIBUTE_NAME} keyword, replace it with attribute name.
  # Otherwise, generate message by prepending the attribute name to message
  if opts == [:exclude_attribute_name]
    error_message = message
  elsif message.gsub!("{ATTRIBUTE_NAME}", attribute_name(attribute).downcase)
    error_message = message
  else
    error_message = "#{attribute_name(attribute).capitalize} #{message}"
  end
  
  # If first error message, encapsulate in an array, otherwise append to existing array
  if self.vet_errors[attribute] == nil
    self.vet_errors[attribute] = [error_message]
  else
    self.vet_errors[attribute] << error_message
  end
  
  # Return false so test definitions don't all need to themselves (if you're adding an error the test didn't pass)
  return false
end

.attribute_name(attribute) ⇒ Object

Return user-defined attribute name if available, otherwise return code attribute name with underscores and dashes removed



176
177
178
179
180
181
182
# File 'lib/vet.rb', line 176

def attribute_name(attribute)
  if defined? self.vet_attribute_names[attribute]
    return self.vet_attribute_names[attribute]
  else
    return attribute.to_s.gsub(/[_-]/, " ")
  end
end

.has_length_in_range(attribute, new_value, range) ⇒ Object



61
62
63
64
65
# File 'lib/vet.rb', line 61

def has_length_in_range(attribute, new_value, range)
  unless range.include? new_value.length
    add_vet_error(attribute, "must be between #{range.first} and #{range.last} characters long.")
  end
end

.is_an_integer(attribute, new_value) ⇒ Object



47
48
49
50
51
# File 'lib/vet.rb', line 47

def is_an_integer(attribute, new_value)
  unless new_value.to_s.match(%r{\A[\d]+\z})
    add_vet_error(attribute, "must be a whole number.")
  end
end

.is_email_address(attribute, new_value) ⇒ Object

—– REGEX MATCH TESTS —–



84
85
86
87
88
# File 'lib/vet.rb', line 84

def is_email_address(attribute, new_value)
  unless new_value.match(%r{\A([\S]+@[\S]+[\.][\S]{2,})\z})
    add_vet_error(attribute, "must be a valid email address.")
  end
end

.is_equal_to_value(attribute, new_value, good_value) ⇒ Object



21
22
23
24
25
# File 'lib/vet.rb', line 21

def is_equal_to_value(attribute, new_value, good_value)
  unless new_value == good_value
    add_vet_error(attribute, "must be #{good_value}.")
  end
end

.is_identical_to_confirmation(attribute, new_value, confirmation) ⇒ Object



27
28
29
30
31
# File 'lib/vet.rb', line 27

def is_identical_to_confirmation(attribute, new_value, confirmation)
  unless new_value == confirmation
    add_vet_error(attribute, "must match confirmation.")
  end
end

.is_in_range(attribute, new_value, range) ⇒ Object

—– RANGE TESTS —–



55
56
57
58
59
# File 'lib/vet.rb', line 55

def is_in_range(attribute, new_value, range)
  unless range.include? new_value
    add_vet_error(attribute, "must be between #{range.first} and #{range.last}.")
  end
end

.is_instance_of_class(attribute, new_value, class_name) ⇒ Object

—– PROPERTY TESTS —–



41
42
43
44
45
# File 'lib/vet.rb', line 41

def is_instance_of_class(attribute, new_value, class_name)
  unless new_value.class == class_name
    add_vet_error(attribute, "must be a #{class_name}.")
  end
end

.is_not_empty(attribute, new_value) ⇒ Object

—– EQUALITY TESTS —–



15
16
17
18
19
# File 'lib/vet.rb', line 15

def is_not_empty(attribute, new_value)
  unless new_value.empty? == false
    add_vet_error(attribute, "must not be empty.")
  end
end

.is_not_equal_to_value(attribute, new_value, bad_value) ⇒ Object



33
34
35
36
37
# File 'lib/vet.rb', line 33

def is_not_equal_to_value(attribute, new_value, bad_value)
  unless new_value != bad_value
    add_vet_error(attribute, "must not be #{bad_value}.")
  end
end

.is_uri_friendly(attribute, new_value) ⇒ Object



90
91
92
93
94
# File 'lib/vet.rb', line 90

def is_uri_friendly(attribute, new_value)
  unless new_value.match(%r{\A[a-z\d]{1}[a-z\d_-]*[a-z\d]{1}\z|\A[a-z\d]{1}\z})
    add_vet_error(attribute, "must contain only lower-case alphanumeric characters, underscores, and dashes.")
  end
end

.modify_attribute(attribute, new_value) ⇒ Object

Simple wrapper for attribute setter method



148
149
150
# File 'lib/vet.rb', line 148

def modify_attribute(attribute, new_value)
  self.send("#{attribute}=", new_value)
end

.only_contains_specified_objects(attribute, new_value, objects) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/vet.rb', line 67

def only_contains_specified_objects(attribute, new_value, objects)
  is_clean = true
  new_value.each do |object|
    if objects.include?(object) == false
      is_clean = false
    end
  end
  
  if is_clean
    return true
  else
    add_vet_error(attribute, "is not an acceptable value.")
  end
end

.vet(attribute, new_value, *specified_tests) ⇒ Object

Run tests, and modify the attribute if all tests pass



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/vet.rb', line 101

def vet(attribute, new_value, *specified_tests)
  # Make sure attribute is a symbol
  attribute = attribute.to_sym
  
  # Initialize variables if necessary
  if self.vet_errors == nil
    self.vet_errors = {}
  end
  if self.vet_modified_attributes == nil
    self.vet_modified_attributes = []
  end
  
  # Only bother running through tests if the new value is different than the old one
  if self.send(attribute) != new_value
    passed_tests = true
  
    # Combine tests defined in model with tests specificed on method call if applicable
    if defined? self.vet_attribute_tests[attribute]
      tests = specified_tests | self.vet_attribute_tests[attribute]
    else
      tests = specified_tests
    end
  
    tests.each do |test|
      # If test call is an array (i.e. has parameters), use parameters from it
      if test.class == Array
        passed_tests = false if self.send(test[0], attribute, new_value, test[1]) == false
      else
        passed_tests = false if self.send(test, attribute, new_value) == false 
      end
    end
  
    # Only modify the attribute if no tests fail
    if passed_tests
      self.modify_attribute(attribute, new_value)
      self.vet_modified_attributes << attribute
    end
  
    # Return true if attribute was changed, false if it wasn't
    return passed_tests
  else
    # Return false if new value was identical to old one
    return false
  end
end