Module: Modelish::Validations::ClassMethods

Defined in:
lib/modelish/validations.rb

Overview

Class methods for managing validated properties

Instance Method Summary collapse

Instance Method Details

#add_validator(property_name, &validator) ⇒ Object

Sets up a block containing validation logic for a given property. Each property may have 0 or more validators.

Examples:

adding a validator that only allows non-nil values

class MyModel
  include Modelish::Validations
  attr_accessor :foo
  add_validator(:foo) { |val| val.nil? ? 'foo must exist': nil }
end

Parameters:

  • property_name (String, Symbol)

    the name of the property to validate

  • validator (#call)

    the block containing the validation logic; must return either an error object or a string containing the error message if validation fails.



73
74
75
76
77
78
79
80
81
# File 'lib/modelish/validations.rb', line 73

def add_validator(property_name, &validator)
  property = property_name.to_sym
  validators[property] ||= []
  validators[property] << validator

  class_eval do
    attr_accessor property unless method_defined?(property_name)
  end
end

#validate_length(name, value, max_length) ⇒ Object

Validates the length of a value, returning an error when validation fails.

Parameters:

  • name (Symbol, String)

    the property/argument to validate

  • value (#length)

    the value to be validated

  • max_length (#to_i)

    the maximum allowable length

Raises:

  • (ArgumentError)

    when the value is longer than max_length



148
149
150
151
152
153
# File 'lib/modelish/validations.rb', line 148

def validate_length(name, value, max_length)
  if max_length.to_i > 0 && value.to_s.length > max_length.to_i
    message = "#{name} must be less than #{max_length} characters"
    ArgumentError.new(message)
  end
end

#validate_length!(name, value, max_length) ⇒ Object

Validates the length of a value, raising an error to indicate validation failure.

Parameters:

  • name (Symbol, String)

    the property/argument to validate

  • value (#length)

    the value to be validated

  • max_length (#to_i)

    the maximum allowable length

Raises:

  • (ArgumentError)

    when the value is longer than max_length



126
127
128
129
# File 'lib/modelish/validations.rb', line 126

def validate_length!(name, value, max_length)
  error = validate_length(name, value, max_length)
  raise error if error
end

#validate_length?(name, value, max_length) ⇒ true, false

Validates the length of a value, returning a boolean to indicate validation success.

Parameters:

  • name (Symbol, String)

    the property/argument to validate

  • value (#length)

    the value to be validated

  • max_length (#to_i)

    the maximum allowable length

Returns:

  • (true, false)

    true if value does not exceed max_length; false otherwise



137
138
139
# File 'lib/modelish/validations.rb', line 137

def validate_length?(name, value, max_length)
  validate_length(name, value, max_length).nil?
end

#validate_required(args) ⇒ Array<ArgumentError>

Validates the required values, returning a list of errors when validation fails.

Parameters:

  • args (Hash)

    the map of name => value pairs to validate

Returns:

  • (Array<ArgumentError>)

    a list of validation failures



93
94
95
96
97
98
# File 'lib/modelish/validations.rb', line 93

def validate_required(args)
  blanks = args.select { |_k, v| v.nil? || v.to_s.strip.empty? }
  blanks.keys.map do |name|
    ArgumentError.new("#{name} must not be nil or blank")
  end
end

#validate_required!(args) ⇒ Object

Validates the required values, raising an error when validation fails.

Parameters:

  • args (Hash)

    the map of name => value pairs to validate

Raises:

  • (ArgumentError)

    when any value in args hash is nil or empty. The name key will be used to construct an informative error message.



106
107
108
109
# File 'lib/modelish/validations.rb', line 106

def validate_required!(args)
  errors = validate_required(args)
  raise errors.first unless errors.empty?
end

#validate_required?(args) ⇒ true, false

Validates the required values, returning a boolean indicating validation success.

Parameters:

  • args (Hash)

    the map of name => value pairs to validate

Returns:

  • (true, false)

    true when validation passes; false when validation fails



117
118
119
# File 'lib/modelish/validations.rb', line 117

def validate_required?(args)
  validate_required(args).empty?
end

#validate_type(name, value, type) ⇒ ArgumentError

Validates the type of the value, returning an error when the value cannot be converted to the appropriate type.

Parameters:

  • name (Symbol, String)

    the property/argument to validate

  • value (Object)

    the value to be validated

  • type (Class, Proc)

    the type of the class to validate. Supported types include:

    • +Integer+
    • +Float+
    • +Date+
    • +DateTime+
    • +Symbol+
    • any arbitrary +Class+ -- validates based on the results of is_a?

Returns:

  • (ArgumentError)

    when validation fails



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/modelish/validations.rb', line 191

def validate_type(name, value, type)
  error = nil

  begin
    if value && type
      # Can't use a case statement because of the way === is implemented on some classes
      if type == Integer
        is_valid = (value.is_a?(Integer) || value.to_s =~ /^\-?\d+$/)
      elsif type == Float
        is_valid = (value.is_a?(Float) || value.to_s =~ /^\-?\d+\.?\d*$/)
      elsif [Date, DateTime].include?(type)
        is_valid = value.is_a?(type) || (type.parse(value.to_s) rescue false)
      elsif type == Symbol
        is_valid = value.respond_to?(:to_sym)
      else
        is_valid = value.is_a?(type)
      end

      unless is_valid
        message = "#{name} must be of type #{type}, " \
                  "but got #{value.inspect}"
        error = ArgumentError.new(message)
      end
    end
  rescue StandardError => e
    message = "An error occurred validating #{name} with " \
              "value #{value.inspect}: #{e.message}"
    error = ArgumentError.new(message)
  end

  error
end

#validate_type!(name, value, type) ⇒ Object

Validates the type of the value, raising an error when the value is not of the correct type.

Parameters:

Raises:

  • (ArgumentError)

    when the value is not the correct type

See Also:



172
173
174
175
# File 'lib/modelish/validations.rb', line 172

def validate_type!(name, value, type)
  error = validate_type(name, value, type)
  raise error if error
end

#validate_type?(name, value, type) ⇒ true, false

Validates the type of the value, returning a boolean indicating validation outcome.

Parameters:

Returns:

  • (true, false)

    true when the value is the correct type; false otherwise

See Also:



162
163
164
# File 'lib/modelish/validations.rb', line 162

def validate_type?(name, value, type)
  validate_type(name, value, type).nil?
end

#validatorsObject

A map of registered validator blocks, keyed on property_name.



84
85
86
# File 'lib/modelish/validations.rb', line 84

def validators
  @validators ||= {}
end