lib/aequitas/rule/length.rb in aequitas-0.0.1 vs lib/aequitas/rule/length.rb in aequitas-0.0.2
- old
+ new
@@ -2,19 +2,14 @@
require 'aequitas/rule'
module Aequitas
class Rule
- module Length
+ class Length < Rule
- # TODO: DRY this up (also implemented in Rule)
- def self.rules_for(attribute_name, options)
- Array(new(attribute_name, options))
- end
-
# TODO: move options normalization into the validator macros
- def self.new(attribute_name, options)
+ def self.rules_for(attribute_name, options)
options = options.dup
equal = options.values_at(:is, :equals).compact.first
range = options.values_at(:in, :within).compact.first
minimum = options.values_at(:min, :minimum).compact.first
@@ -22,62 +17,66 @@
if minimum && maximum
range ||= minimum..maximum
end
- if equal
- Length::Equal.new(attribute_name, options.merge(:expected => equal))
- elsif range
- Length::Range.new(attribute_name, options.merge(:range => range))
- elsif minimum
- Length::Minimum.new(attribute_name, options.merge(:bound => minimum))
- elsif maximum
- Length::Maximum.new(attribute_name, options.merge(:bound => maximum))
- else
- # raise ArgumentError, "expected one of :is, :equals, :within, :in, :minimum, :min, :maximum, or :max; got #{options.keys.inspect}"
- warn "expected length specification: one of :is, :equals, :in, :within, :min, :minimum, :max, or :maximum; got #{options.keys.inspect}"
- Length::Dummy.new(attribute_name, options)
- end
+ rule =
+ if equal
+ Length::Equal.new(attribute_name, options.merge(:expected => equal))
+ elsif range
+ Length::Range.new(attribute_name, options.merge(:range => range))
+ elsif minimum
+ Length::Minimum.new(attribute_name, options.merge(:bound => minimum))
+ elsif maximum
+ Length::Maximum.new(attribute_name, options.merge(:bound => maximum))
+ else
+ # raise ArgumentError, "expected one of :is, :equals, :within, :in, :minimum, :min, :maximum, or :max; got #{options.keys.inspect}"
+ warn "expected length specification: one of :is, :equals, :in, :within, :min, :minimum, :max, or :maximum; got #{options.keys.inspect}"
+ Length::Dummy.new(attribute_name, options)
+ end
+
+ [rule]
end
- class Dummy < Rule
- include Length
+ class Dummy < Length
end
def valid?(resource)
value = attribute_value(resource)
- skip?(value) || valid_length?(value_length(value.to_s))
+ skip?(value) || valid_length?(value_length(value))
end
- private
-
def valid_length?(length)
raise NotImplementedError, "#{self.class}#valid_length? must be implemented"
end
# Return the length in characters
#
- # @param [#to_str] value
- # the string to get the number of characters for
+ # @param [#length, #to_s] value
+ # the value to get the length of. if it does not respond to #length,
+ # then #to_s will be called, and the length of that will be calculated
+ # instead
#
# @return [Integer]
- # the number of characters in the string
+ # the length of the value
#
# @api private
def value_length(value)
- value.to_str.length
+ value.length
+ rescue NoMethodError
+ value.to_s.length
end
if RUBY_VERSION < '1.9'
# calculate length of multi-byte-encoded strings
# as characters rather than bytes
def value_length(value)
value.to_str.scan(/./u).size
end
end
- end # module Length
+ end # class Length
end # class Rule
end # module Aequitas
# meh, I don't like doing this, but the superclass must be loaded before subclasses
require 'aequitas/rule/length/equal'