Module: Gourami::Validations

Includes:
FormattingConstants
Included in:
Form
Defined in:
lib/gourami/validations.rb

Constant Summary

Constants included from FormattingConstants

FormattingConstants::EMAIL_FORMAT, FormattingConstants::HEX_COLOR_FORMAT, FormattingConstants::ISRC_FORMAT

Instance Method Summary collapse

Instance Method Details

#any_errors?Boolean

Return true if there are any errors.

Returns:

  • (Boolean)


79
80
81
# File 'lib/gourami/validations.rb', line 79

def any_errors?
  errors.reject{ |k,v| v.empty? }.any?
end

#append_error(attribute_name, message) ⇒ Object

Overridden and super invoked from Extensions::Resources



101
102
103
# File 'lib/gourami/validations.rb', line 101

def append_error(attribute_name, message)
  append_root_error(attribute_name, message)
end

#append_root_error(attribute_name, error) ⇒ Object

Append an error to the given attribute.

Parameters:

  • attribute_name (Symbol, nil)

    nil for base

  • error (Symbol, String)

    The error identifier.



88
89
90
# File 'lib/gourami/validations.rb', line 88

def append_root_error(attribute_name, error)
  errors[attribute_name] << error
end

#attribute_has_errors?(attribute_name) ⇒ Boolean

Return true if there given attribute has any errors.

Returns:

  • (Boolean)


74
75
76
# File 'lib/gourami/validations.rb', line 74

def attribute_has_errors?(attribute_name)
  errors[attribute_name.to_sym].any?
end

#clear_and_set_errors(new_errors) ⇒ Object

Replace the existing errors with the provided errors Hash.

Parameters:

  • new_errors

    Hash<Symbol, Array>



57
58
59
60
61
62
63
# File 'lib/gourami/validations.rb', line 57

def clear_and_set_errors(new_errors)
  new_errors = new_errors.dup
  errors.clear
  errors.merge!(new_errors)

  errors
end

#current_resourceObject

Overridden and super invoked from Extensions::Resources



96
97
98
# File 'lib/gourami/validations.rb', line 96

def current_resource
  self
end

#errorsHash<Symbol, nil>, Array<Symbol, String>

Get the current form errors Hash.

Returns:

  • (Hash<Symbol, nil>, Array<Symbol, String>)

    The errors Hash, having the Symbol attribute names as keys and an array of errors (Symbols) as the value.



38
39
40
# File 'lib/gourami/validations.rb', line 38

def errors
  @errors ||= Hash.new { |hash, key| hash[key] = [] }
end

#get_current_resource_attribute_value(attribute_name) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/gourami/validations.rb', line 105

def get_current_resource_attribute_value(attribute_name)
  resource = current_resource
  # If resource responds to the attribute, return the value. Otherwise, check if it's a hash and return the value for the attribute.
  if resource.respond_to?(attribute_name)
    resource.send(attribute_name)
  elsif resource.respond_to?(:[])
    if resource.key?(attribute_name.to_sym)
      resource[attribute_name.to_sym]
    elsif resource.key?(attribute_name.to_s)
      resource[attribute_name.to_s]
    end
  else
    nil
  end
end

#handle_validation_error(error) ⇒ Object



69
70
71
# File 'lib/gourami/validations.rb', line 69

def handle_validation_error(error)
  clear_and_set_errors(error.errors) unless error.errors.nil?
end

#perform!Object

Validate and perform the form actions. If any errors come up during the

validation or the #perform method, raise an exception with the errors.


16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/gourami/validations.rb', line 16

def perform!
  if valid?
    begin
      returned = perform
    rescue Gourami::ValidationError => error
      handle_validation_error(error)
      raise
    end
  end

  if any_errors?
    raise_validate_errors
  end

  returned
end

#raise_validate_errorsObject

Raises:



65
66
67
# File 'lib/gourami/validations.rb', line 65

def raise_validate_errors
  raise ValidationError.new(errors)
end

#valid?Boolean

Determine if current form instance is valid by running the validations

specified on #validate.

Returns:

  • (Boolean)


46
47
48
49
50
# File 'lib/gourami/validations.rb', line 46

def valid?
  errors.clear
  validate
  !any_errors?
end

#validateObject



8
9
10
# File 'lib/gourami/validations.rb', line 8

def validate
  # Override to add custom validations
end

#validate_any(attribute_name, message = nil) ⇒ Object

Validate the value of the given attribute is not empty. Appends :cant_be_empty error.

Parameters:

  • attribute_name (Symbol)


239
240
241
242
243
244
# File 'lib/gourami/validations.rb', line 239

def validate_any(attribute_name, message = nil)
  value = get_current_resource_attribute_value(attribute_name)
  if value && value.empty?
    append_error(attribute_name, message || :cant_be_empty)
  end
end

#validate_color_format(attribute_name, message = nil) ⇒ Object



159
160
161
# File 'lib/gourami/validations.rb', line 159

def validate_color_format(attribute_name, message = nil)
  validate_format(attribute_name, HEX_COLOR_FORMAT, message)
end

#validate_decimal_places(attribute_name, max:, min: 0, max_message: nil, min_message: nil) ⇒ Object

Ensure the provided numeric attribute has the correct number of decimal places within the given range.

Examples:

validate_decimal_places(:price, max: 2)
validate_decimal_places(:price, min: 2, min_message: "Price must have at least 2 decimal places.")

Parameters:

  • attribute_name (Symbol)
  • options (Hash)

    a customizable set of options



294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/gourami/validations.rb', line 294

def validate_decimal_places(attribute_name, max:, min: 0, max_message: nil, min_message: nil)
  value = get_current_resource_attribute_value(attribute_name)&.to_s
  return unless value

  decimal_places = value.split(".", 2).last&.length || 0

  if max && max > 0 && decimal_places > max
    append_error(attribute_name, max_message || :too_many_decimal_places)
  end

  if min && min > 0 && decimal_places < min
    append_error(attribute_name, min_message || :too_few_decimal_places)
  end
end

#validate_email_format(attribute_name, message = nil) ⇒ Object

Validate the email format. If the value does not match the email format,

append the :is_invalid error to the attribute.

Parameters:

  • attribute_name (Symbol)


151
152
153
# File 'lib/gourami/validations.rb', line 151

def validate_email_format(attribute_name, message = nil)
  validate_format(attribute_name, EMAIL_FORMAT, message)
end

#validate_filetype(attribute_name, filetypes, message = nil) ⇒ Object

Validate the type of the file sent if included in the list. If it’s not,

append an :invalid_file error to the attribute.

Parameters:

  • attribute_name (Symbol)
  • filetypes (Array<String>)


251
252
253
254
255
256
# File 'lib/gourami/validations.rb', line 251

def validate_filetype(attribute_name, filetypes, message = nil)
  value = get_current_resource_attribute_value(attribute_name)
  if value && !filetypes.include?(value[:type].to_s.split("/").first)
    append_error(attribute_name, message || :is_invalid)
  end
end

#validate_format(attribute_name, format, message = nil) ⇒ Object

Validate the format of the attribute value. If the value does not match

the regexp given, append :is_invalid error to the attribute.

Parameters:

  • attribute_name (Symbol)
  • format (Regexp)


168
169
170
171
172
173
# File 'lib/gourami/validations.rb', line 168

def validate_format(attribute_name, format, message = nil)
  value = get_current_resource_attribute_value(attribute_name)
  if value && !(format =~ value)
    append_error(attribute_name, message || :is_invalid)
  end
end

#validate_inclusion(attribute_name, list, message = nil) ⇒ Object

Validate the value of the given attribute is included in the list. If

the value is not included in the list, append the :not_listed error to
the attribute.

Parameters:

  • attribute_name (Symbol)
  • list (Array)


216
217
218
219
220
221
# File 'lib/gourami/validations.rb', line 216

def validate_inclusion(attribute_name, list, message = nil)
  value = get_current_resource_attribute_value(attribute_name)
  if value && !list.include?(value)
    append_error(attribute_name, message || :isnt_listed)
  end
end

#validate_inclusion_of_each(attribute_name, list, message = nil) ⇒ Object

Validate the presence of each object in attribute name within list. If the object

is not included in the list, append the :not_listed error to the attribute.


225
226
227
228
229
230
231
232
233
# File 'lib/gourami/validations.rb', line 225

def validate_inclusion_of_each(attribute_name, list, message = nil)
  value = get_current_resource_attribute_value(attribute_name)
  value && value.each do |obj|
    unless list.include?(obj)
      append_error(attribute_name, message || "#{obj} isn't listed")
      break
    end
  end
end

#validate_isrc_format(attribute_name, message = nil) ⇒ Object



155
156
157
# File 'lib/gourami/validations.rb', line 155

def validate_isrc_format(attribute_name, message = nil)
  validate_format(attribute_name, ISRC_FORMAT, message)
end

#validate_length(attribute_name, options = {}) ⇒ Object

Validate the length of a String, Array or any other form attribute which

responds to #size. If the value is too short, append the :too_short
error to the attribute. If the value is too long append the :too_long
error to the attribute.

Parameters:

  • attribute_name (Symbol)
  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :min (Integer, nil) — default: nil
  • :max (Integer, nil) — default: nil


183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/gourami/validations.rb', line 183

def validate_length(attribute_name, options = {})
  # TODO: Support :unless_already_invalid => true in more validators.
  return if options.fetch(:unless_already_invalid, false) && attribute_has_errors?(attribute_name)

  min = options.fetch(:min, nil)
  max = options.fetch(:max, nil)
  value = get_current_resource_attribute_value(attribute_name)

  return if options[:allow_blank] && value.blank?

  if value
    length = value.size
    did_append_error = false

    if min && length < min
      did_append_error = true
      append_error(attribute_name, options.fetch(:min_message, nil) || :is_too_short)
    end
    if max && length > max
      did_append_error = true
      append_error(attribute_name, options.fetch(:max_message, nil) || :is_too_long)
    end

    errors[attribute_name] if did_append_error
  end
end

#validate_presence(attribute_name, message = nil) ⇒ Object

Validate the presence of the attribute value. If the value is nil or

false append the :cant_be_empty error to the attribute.

Parameters:

  • attribute_name (Symbol)


125
126
127
128
129
130
# File 'lib/gourami/validations.rb', line 125

def validate_presence(attribute_name, message = nil)
  value = get_current_resource_attribute_value(attribute_name)
  if !value || value.to_s.strip.empty?
    append_error(attribute_name, message || :cant_be_empty)
  end
end

#validate_range(attribute_name, options = {}) ⇒ Object

TODO: Spec return value in spec/validations_spec.rb Validate the range in which the attribute can be. If the value is less

than the min a :less_than_min error will be appended. If the value is
greater than the max a :greater_than_max error will be appended.

Parameters:

  • attribute_name (Symbol)
  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :min (Integer) — default: nil

    The minimum value the attribute can take, if nil, no validation is made.

  • :max (Integer) — default: nil

    The maximum value the attribute can take, if nil, no validation is made.



268
269
270
271
272
273
274
275
276
277
# File 'lib/gourami/validations.rb', line 268

def validate_range(attribute_name, options = {})
  value = get_current_resource_attribute_value(attribute_name)

  return unless value

  min = options.fetch(:min, nil)
  max = options.fetch(:max, nil)
  append_error(attribute_name, options.fetch(:min_message, nil) || :less_than_min) if min && value < min
  append_error(attribute_name, options.fetch(:max_message, nil) || :greater_than_max) if max && value > max
end

#validate_uniqueness(attribute_name, message = nil, &block) ⇒ Object

Validate the uniqueness of the attribute value. The uniqueness is

determined by the block given. If the value is not unique, append the
:is_duplicated error to the attribute.

Parameters:

  • attribute_name (Symbol)
  • block (Proc)

    A block to determine if a given value is unique or not. It receives the value and returns true if the value is unique.



140
141
142
143
144
145
# File 'lib/gourami/validations.rb', line 140

def validate_uniqueness(attribute_name, message = nil, &block)
  value = get_current_resource_attribute_value(attribute_name)
  unless block.call(value)
    append_error(attribute_name, message || :is_duplicated)
  end
end