Last active
December 22, 2015 06:29
-
-
Save ephemeralsnow/6431596 to your computer and use it in GitHub Desktop.
ActiveModel::Validations::ByteLengthValidator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ActiveModel | |
# == Active \Model ByteLength \Validator | |
module Validations | |
class ByteLengthValidator < EachValidator # :nodoc: | |
MESSAGES = { is: :wrong_length, minimum: :too_short, maximum: :too_long, encoding: "encode_error" }.freeze | |
CHECKS = { is: :==, minimum: :>=, maximum: :<= }.freeze | |
RESERVED_OPTIONS = [:minimum, :maximum, :within, :is, :too_short, :too_long] | |
def initialize(options) | |
if range = (options.delete(:in) || options.delete(:within)) | |
raise ArgumentError, ":in and :within must be a Range" unless range.is_a?(Range) | |
options[:minimum], options[:maximum] = range.min, range.max | |
end | |
if options[:allow_blank] == false && options[:minimum].nil? && options[:is].nil? | |
options[:minimum] = 1 | |
end | |
if options[:encoding].nil? | |
options[:encoding] = Encoding.default_external | |
end | |
super | |
end | |
def check_validity! | |
keys = CHECKS.keys & options.keys | |
if keys.empty? | |
raise ArgumentError, 'Range unspecified. Specify the :in, :within, :maximum, :minimum, or :is option.' | |
end | |
keys.each do |key| | |
value = options[key] | |
unless (value.is_a?(Integer) && value >= 0) || value == Float::INFINITY | |
raise ArgumentError, ":#{key} must be a nonnegative Integer or Infinity" | |
end | |
end | |
end | |
def validate_each(record, attribute, value) | |
begin | |
value = encode(value) | |
rescue EncodingError => e | |
record.errors.add(attribute, MESSAGES[:encoding]) | |
else | |
value_length = value.respond_to?(:bytesize) ? value.bytesize : encode(value.to_s).bytesize | |
errors_options = options.except(*RESERVED_OPTIONS) | |
CHECKS.each do |key, validity_check| | |
next unless check_value = options[key] | |
if !value.nil? || skip_nil_check?(key) | |
next if value_length.send(validity_check, check_value) | |
end | |
errors_options[:count] = check_value | |
default_message = options[MESSAGES[key]] | |
errors_options[:message] ||= default_message if default_message | |
record.errors.add(attribute, MESSAGES[key], errors_options) | |
end | |
end | |
end | |
private | |
def encode(value) | |
if options[:encoding] && value.kind_of?(String) | |
value.encode(options[:encoding], | |
invalid: options[:invalid], | |
:undef => options[:undef], | |
replace: options[:replace], | |
xml: options[:xml], | |
universal_newline: options[:universal_newline], | |
cr_newline: options[:cr_newline], | |
crlf_newline: options[:crlf_newline]) | |
end || value | |
end | |
def skip_nil_check?(key) | |
key == :maximum && options[:allow_nil].nil? && options[:allow_blank].nil? | |
end | |
end | |
module HelperMethods | |
def validates_bytelength_of(*attr_names) | |
validates_with ByteLengthValidator, _merge_attributes(attr_names) | |
end | |
alias_method :validates_bytesize_of, :validates_bytelength_of | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment