Module: Validation::ClassMethods

Defined in:
lib/rcap/validation.rb,
lib/rcap/custom_validators.rb

Overview

Validation class methods.

Constant Summary collapse

NUMBER_RE =
/^\d*\.{0,1}\d+$/.freeze
INTEGER_RE =
/\A[+-]?\d+\Z/.freeze
CAP_NUMBER_REGEX =
Regexp.new('^-{0,1}\d*\.{0,1}\d+$')
CAP_INTEGER_REGEX =
Regexp.new('\-{0,1}A[+-]?\d+\Z')

Instance Method Summary collapse

Instance Method Details

#has_validations?Boolean

Returns true if validations are defined.

Returns:

  • (Boolean)


127
128
129
# File 'lib/rcap/validation.rb', line 127

def has_validations?
  !validations.empty?
end

#skip_superclass_validationsObject



140
141
142
# File 'lib/rcap/validation.rb', line 140

def skip_superclass_validations
  @skip_superclass_validations = true
end

#validate(o) ⇒ Object

Validates the given instance.



132
133
134
135
136
137
138
# File 'lib/rcap/validation.rb', line 132

def validate(o)
  superclass.validate(o) if superclass.respond_to?(:validate) && !@skip_superclass_validations
  validations.each do |att, procs|
    v = o.send(att)
    procs.each { |p| p[o, att, v] }
  end
end

#validates(&block) ⇒ Object

Defines validations by converting a longhand block into a series of shorthand definitions. For example:

class MyClass
  include Validation
  validates do
    length_of :name, :minimum => 6
    length_of :password, :minimum => 8
  end
end

is equivalent to:

class MyClass
  include Validation
  validates_length_of :name, :minimum => 6
  validates_length_of :password, :minimum => 8
end


117
118
119
# File 'lib/rcap/validation.rb', line 117

def validates(&block)
  Generator.new(self, &block)
end

#validates_acceptance_of(*atts) ⇒ Object

Validates acceptance of an attribute.



156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/rcap/validation.rb', line 156

def validates_acceptance_of(*atts)
  opts = {
    message: 'is not accepted',
    allow_nil: true,
    accept: '1'
  }.merge!(atts.extract_options!)

  validates_each(*atts) do |o, a, v|
    next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])

    o.errors[a] << opts[:message] unless v == opts[:accept]
  end
end

#validates_collection_of(*attributes) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
# File 'lib/rcap/custom_validators.rb', line 61

def validates_collection_of(*attributes)
  options = {
    message: 'contains an invalid element'
  }.merge!(attributes.extract_options!)

  validates_each(*attributes) do |object, attribute, collection|
    next if (collection.nil? && options[:allow_nil]) || (collection.empty? && options[:allow_empty])

    object.errors[attribute] << options[:message] unless collection.all?(&:valid?)
  end
end

#validates_conditional_presence_of(*attributes) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/rcap/custom_validators.rb', line 90

def validates_conditional_presence_of(*attributes)
  options = {
    message: 'is not defined but is required by :contingent_attribute'
  }.merge!(attributes.extract_options!)

  validates_each(*attributes) do |object, attribute, value|
    contingent_attribute_value = object.send(options[:when])
    required_contingent_attribute_value = options[:is]

    if contingent_attribute_value.nil? || contingent_attribute_value != required_contingent_attribute_value && !options[:is].blank?
      next
    end

    if value.blank?
      object.errors[attribute] << options[:message].gsub(/:contingent_attribute/, options[:whenn].to_s)
    end
  end
end

#validates_confirmation_of(*atts) ⇒ Object

Validates confirmation of an attribute.



171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/rcap/validation.rb', line 171

def validates_confirmation_of(*atts)
  opts = {
    message: 'is not confirmed'
  }.merge!(atts.extract_options!)

  validates_each(*atts) do |o, a, v|
    next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])

    c = o.send(:"#{a}_confirmation")
    o.errors[a] << opts[:message] unless v == c
  end
end

#validates_dependency_of(*attributes) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/rcap/custom_validators.rb', line 73

def validates_dependency_of(*attributes)
  options = {
    message: 'is dependent on :attribute being defined'
  }.merge!(attributes.extract_options!)

  validates_each(*attributes) do |object, attribute, value|
    next if value.blank?

    contingent_on_attribute = object.send(options[:on])
    contingent_on_attribute_value = options[:with_value]

    if contingent_on_attribute.nil? || !contingent_on_attribute_value.nil? && contingent_on_attribute_value != contingent_on_attribute
      object.errors[attribute] << options[:message].gsub(/:attribute/, options[:on].to_s)
    end
  end
end

#validates_each(*atts, &block) ⇒ Object

Adds a validation for each of the given attributes using the supplied block. The block must accept three arguments: instance, attribute and value, e.g.:

validates_each :name, :password do |object, attribute, value|
  object.errors[attribute] << 'is not nice' unless value.nice?
end


151
152
153
# File 'lib/rcap/validation.rb', line 151

def validates_each(*atts, &block)
  atts.each { |a| validations[a] << block }
end

#validates_equality_of_first_and_last(*attributes) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/rcap/custom_validators.rb', line 141

def validates_equality_of_first_and_last(*attributes)
  options = {
    message: 'does not have equal first and last elements'
  }.merge!(attributes.extract_options!)

  validates_each(*attributes) do |object, attribute, collection|
    next if collection.nil? && options[:allow_nil]
    next if collection.empty? && options[:allow_empty]

    object.errors[attribute] << options[:message] unless collection.first == collection.last
  end
end

#validates_format_of(*atts) ⇒ Object

Validates the format of an attribute.



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/rcap/validation.rb', line 185

def validates_format_of(*atts)
  opts = {
    message: 'is invalid'
  }.merge!(atts.extract_options!)

  unless opts[:with].is_a?(Regexp)
    raise ArgumentError, 'A regular expression must be supplied as the :with option of the options hash'
  end

  validates_each(*atts) do |o, a, v|
    next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])

    o.errors[a] << opts[:message] unless v.to_s =~ opts[:with]
  end
end

#validates_inclusion_of(*attributes) ⇒ Object

Examples:

validates_inclusion_of( :status, :in => VALID_STATUSES )


10
11
12
13
14
15
16
17
18
19
20
# File 'lib/rcap/custom_validators.rb', line 10

def validates_inclusion_of(*attributes)
  options = {
    message: 'is not in the required range'
  }.merge!(attributes.extract_options!)

  validates_each(*attributes) do |object, attribute, value|
    next if  value.nil? && options[:allow_nil]

    object.errors[attribute] << options[:message] unless options[:in].include?(value)
  end
end

#validates_inclusion_of_members_of(*attributes) ⇒ Object

Will validate all members of a collection are found in a given collection.

Examples:

validates_inclusion_of_members_of( :categories, :in => VALID_CATEGORIES )


25
26
27
28
29
30
31
32
33
34
35
# File 'lib/rcap/custom_validators.rb', line 25

def validates_inclusion_of_members_of(*attributes)
  options = {
    message: 'contains members that are not valid'
  }.merge!(attributes.extract_options!)

  validates_each(*attributes) do |object, attribute, collection|
    next if (collection.nil? && options[:allow_nil]) || (collection.empty? && options[:allow_empty])

    object.errors[attribute] << options[:message] unless collection.all? { |member| options[:in].include?(member) }
  end
end

#validates_length_of(*atts) ⇒ Object

Validates the length of an attribute.



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/rcap/validation.rb', line 202

def validates_length_of(*atts)
  opts = {
    too_long: 'is too long',
    too_short: 'is too short',
    wrong_length: 'is the wrong length'
  }.merge!(atts.extract_options!)

  validates_each(*atts) do |o, a, v|
    next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])

    if m = opts[:maximum]
      o.errors[a] << (opts[:message] || opts[:too_long]) unless v && v.size <= m
    end
    if m = opts[:minimum]
      o.errors[a] << (opts[:message] || opts[:too_short]) unless v && v.size >= m
    end
    if i = opts[:is]
      o.errors[a] << (opts[:message] || opts[:wrong_length]) unless v && v.size == i
    end
    if w = opts[:within]
      o.errors[a] << (opts[:message] || opts[:wrong_length]) unless v && w.include?(v.size)
    end
  end
end

#validates_length_of_members_of(*attributes) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
# File 'lib/rcap/custom_validators.rb', line 37

def validates_length_of_members_of(*attributes)
  options = {
    message: 'contains members with incorrect length'
  }.merge!(attributes.extract_options!)

  validates_each(*attributes) do |object, attribute, collection|
    next if (collection.nil? && options[:allow_nil]) || (collection.empty? && options[:allow_empty])

    object.errors[attribute] << options[:message] unless options[:minimum] && collection.length >= options[:minimum]
  end
end

#validates_numericality_of(*attributes) ⇒ Object

Validates whether an attribute is a number.



231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/rcap/validation.rb', line 231

def validates_numericality_of(*atts)
  opts = {
    message: 'is not a number'
  }.merge!(atts.extract_options!)

  re = opts[:only_integer] ? INTEGER_RE : NUMBER_RE

  validates_each(*atts) do |o, a, v|
    next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])

    o.errors[a] << opts[:message] unless v.to_s =~ re
  end
end

#validates_presence_of(*atts) ⇒ Object

Validates the presence of an attribute.



246
247
248
249
250
251
252
253
254
# File 'lib/rcap/validation.rb', line 246

def validates_presence_of(*atts)
  opts = {
    message: 'is not present'
  }.merge!(atts.extract_options!)

  validates_each(*atts) do |o, a, v|
    o.errors[a] << opts[:message] unless v && !v.blank?
  end
end

#validates_responsiveness_of(*attributes) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/rcap/custom_validators.rb', line 127

def validates_responsiveness_of(*attributes)
  options = {
    message: 'does not respond to the given method'
  }.merge!(attributes.extract_options!)

  validates_each(*attributes) do |object, attribute, _value|
    next if  collection.nil? && options[:allow_nil]

    unless options[:to].all? { |method_name| object.respond_to?(method_name) }
      object.errors[attribute] << options [:message]
    end
  end
end

#validates_validity_of(*attributes) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
# File 'lib/rcap/custom_validators.rb', line 49

def validates_validity_of(*attributes)
  options = {
    message: 'is not valid'
  }.merge!(attributes.extract_options!)

  validates_each(*attributes) do |object, attribute, value|
    next if  value.nil? && options[:allow_nil]

    object.errors[attribute] << options[:message] unless value&.valid?
  end
end

#validationsObject

Returns the validations hash for the class.



122
123
124
# File 'lib/rcap/validation.rb', line 122

def validations
  @validations ||= Hash.new { |h, k| h[k] = [] }
end