Module: MotionModel::Validatable

Defined in:
lib/motion_model/validatable.rb

Defined Under Namespace

Modules: ClassMethods Classes: RecordInvalid, ValidationSpecificationError

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



7
8
9
10
# File 'lib/motion_model/validatable.rb', line 7

def self.included(base)
  base.extend(ClassMethods)
  base.instance_variable_set('@validations', [])
end

Instance Method Details

#add_message(field, message) ⇒ Object

Add a message for field to the messages collection.



167
168
169
# File 'lib/motion_model/validatable.rb', line 167

def add_message(field, message)
  @messages.push({field.to_sym => message})
end

#each_validation_for(field) ⇒ Object

nodoc



82
83
84
85
86
87
88
# File 'lib/motion_model/validatable.rb', line 82

def each_validation_for(field) #nodoc
  self.class.validations.select{|validation| validation.has_key?(field)}.each do |validation|
    validation.each_pair do |field, validation_hash|
      yield validation_hash
    end
  end
end

#error_messagesObject

Raw array of hashes of error messages.



61
62
63
# File 'lib/motion_model/validatable.rb', line 61

def error_messages
  @messages
end

#error_messages_for(field) ⇒ Object

Array of messages for a given field. Results are always an array because a field can fail multiple validations.



67
68
69
70
# File 'lib/motion_model/validatable.rb', line 67

def error_messages_for(field)
  key = field.to_sym
  error_messages.select{|message| message.has_key?(key)}.map{|message| message[key]}
end

#save(options = { :validate => true}) ⇒ Object

It doesn’t save when validations fails



36
37
38
# File 'lib/motion_model/validatable.rb', line 36

def save(options={ :validate => true})
  (valid? || !options[:validate]) ? super : false
end

#save!Object

it fails loudly

Raises:



41
42
43
44
# File 'lib/motion_model/validatable.rb', line 41

def save!
  raise RecordInvalid.new('failed validation') unless valid?
  save
end

#valid?Boolean

This has two functions:

  • First, it triggers validations.

  • Second, it returns the result of performing the validations.

Returns:

  • (Boolean)


51
52
53
54
55
56
57
58
# File 'lib/motion_model/validatable.rb', line 51

def valid?
  @messages = []
  @valid = true
  self.class.validations.each do |validations|
    validate_each(validations)
  end
  @valid
end

#validate_each(validations) ⇒ Object

nodoc



72
73
74
75
76
# File 'lib/motion_model/validatable.rb', line 72

def validate_each(validations) #nodoc
  validations.each_pair do |field, validation|
    @valid &&= validate_one field, validation
  end
end

#validate_email(field, value, setting) ⇒ Object



150
151
152
153
154
155
156
# File 'lib/motion_model/validatable.rb', line 150

def validate_email(field, value, setting)
  if value.is_a?(String) || value.nil?
    result = value.nil? || value.match(/\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i).nil?
    add_message(field, "#{field.to_s} does not appear to be an email address.") if result
  end
  return !result
end

#validate_for(field, value) ⇒ Object

Validates an arbitrary string against a specific field’s validators. Useful before setting the value of a model’s field. I.e., you get data from a form, do a validate_for(:my_field, that_data) and if it succeeds, you do obj.my_field = that_data.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/motion_model/validatable.rb', line 94

def validate_for(field, value)
  @messages = []
  key = field.to_sym
  result = true
  each_validation_for(key) do |validation|
    validation.each_pair do |validation_type, setting|
      method = validation_method(validation_type)
      if self.respond_to? method
        value.strip! if value.is_a?(String)
        result &&= self.send(method, field, value, setting)
      end
    end
  end
  result
end

#validate_format(field, value, setting) ⇒ Object

Validates contents of field against a given Regexp. This can be tricky because you need to anchor both sides in most cases using A and Z to get a reliable match.



160
161
162
163
164
# File 'lib/motion_model/validatable.rb', line 160

def validate_format(field, value, setting)
  result = value.nil? || setting.match(value).nil?
  add_message(field, "#{field.to_s} does not appear to be in the proper format.") if result
  return !result
end

#validate_length(field, value, setting) ⇒ Object

Validates that the length is in a given range of characters. E.g.,

validate :name,   :length => 5..8


141
142
143
144
145
146
147
148
# File 'lib/motion_model/validatable.rb', line 141

def validate_length(field, value, setting)
  if value.is_a?(String) || value.nil?
    result = value.nil? || (value.length < setting.first || value.length > setting.last)
    add_message(field, "incorrect value supplied for #{field.to_s} -- should be between #{setting.first} and #{setting.last} characters long.") if result
    return !result
  end
  return false
end

#validate_one(field, validation) ⇒ Object

nodoc



110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/motion_model/validatable.rb', line 110

def validate_one(field, validation) #nodoc
  result = true
  validation.each_pair do |validation_type, setting|
    if self.respond_to? validation_method(validation_type)
      value = self.send(field)
      result &&= self.send(validation_method(validation_type), field, value.is_a?(String) ? value.strip : value, setting)
    else
      ex = ValidationSpecificationError.new("unknown validation type :#{validation_type.to_s}")
    end
  end
  result
end

#validate_presence(field, value, setting) ⇒ Object

Validates that something has been endntered in a field. Should catch Fixnums, Bignums and Floats. Nils and Strings should be handled as well, Arrays, Hashes and other datatypes will not.



126
127
128
129
130
131
132
133
134
135
136
# File 'lib/motion_model/validatable.rb', line 126

def validate_presence(field, value, setting)
  if(value.is_a?(Numeric)) 
    return true
  elsif value.is_a?(String) || value.nil?
    result = value.nil? || ((value.length == 0) == setting)
    additional_message = setting ? "non-empty" : "non-empty"
    add_message(field, "incorrect value supplied for #{field.to_s.humanize} -- should be #{additional_message}.") if result
    return !result
  end
  return false
end

#validation_method(validation_type) ⇒ Object

nodoc



78
79
80
# File 'lib/motion_model/validatable.rb', line 78

def validation_method(validation_type) #nodoc
  validation_method = "validate_#{validation_type}".to_sym
end