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.



163
164
165
# File 'lib/motion_model/validatable.rb', line 163

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



146
147
148
149
150
151
152
# File 'lib/motion_model/validatable.rb', line 146

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.



156
157
158
159
160
# File 'lib/motion_model/validatable.rb', line 156

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


137
138
139
140
141
142
143
144
# File 'lib/motion_model/validatable.rb', line 137

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 entered in a field



124
125
126
127
128
129
130
131
132
# File 'lib/motion_model/validatable.rb', line 124

def validate_presence(field, value, setting)
  if 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