Skip to content

Instantly share code, notes, and snippets.

@forsbergplustwo
Created April 15, 2021 13:27
Show Gist options
  • Save forsbergplustwo/72fc79be40ca5a6255a99a1a890a536f to your computer and use it in GitHub Desktop.
Save forsbergplustwo/72fc79be40ca5a6255a99a1a890a536f to your computer and use it in GitHub Desktop.
require "ruby-boolean"
class TypeValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
value_to_test = type_before_coercion(record, attribute, value)
expected_type = type_class(options[:with])
record.errors.add attribute, (options[:message] || "argument of #{record.class} is not of class: #{options[:with].to_s.camelize}. It is class: #{value.class} with value of #{value}") unless value_to_test.is_a?(expected_type)
end
private
def type_class(type)
@type_class ||= type.is_a?(Class) ? type : symbol_class(type)
end
def symbol_class(symbol)
{
array: Array,
boolean: Boolean,
float: Float,
hash: Hash,
integer: Integer,
string: String,
symbol: Symbol,
time: Time,
date: Date,
big_decimal: BigDecimal,
}[symbol] || fail(UnsupportedType,
"Unsupported type #{symbol.to_s.camelize} given for validates_type.")
end
def type_before_coercion(record, attribute, value)
record.try(:"#{attribute}_before_type_cast") || value
end
class UnsupportedType < StandardError; end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment