thoughtbot--shoulda-matchers/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb

174 lines
5.4 KiB
Ruby
Raw Normal View History

2010-12-15 22:34:19 +00:00
module Shoulda # :nodoc:
module Matchers
module ActiveModel # :nodoc:
2010-12-15 22:34:19 +00:00
# Ensures that the length of the attribute is validated. Only works with
# string/text columns because it uses a string to check length.
2010-12-15 22:34:19 +00:00
#
# Options:
# * <tt>is_at_least</tt> - minimum length of this attribute
# * <tt>is_at_most</tt> - maximum length of this attribute
# * <tt>is_equal_to</tt> - exact requred length of this attribute
# * <tt>with_short_message</tt> - value the test expects to find in
# <tt>errors.on(:attribute)</tt>. Regexp or string. Defaults to the
# translation for :too_short.
# * <tt>with_long_message</tt> - value the test expects to find in
# <tt>errors.on(:attribute)</tt>. Regexp or string. Defaults to the
# translation for :too_long.
# * <tt>with_message</tt> - value the test expects to find in
# <tt>errors.on(:attribute)</tt>. Regexp or string. Defaults to the
# translation for :wrong_length. Used in conjunction with
# <tt>is_equal_to</tt>.
#
# Examples:
# it { should ensure_length_of(:password).
# is_at_least(6).
# is_at_most(20) }
# it { should ensure_length_of(:name).
# is_at_least(3).
# with_short_message(/not long enough/) }
# it { should ensure_length_of(:ssn).
# is_equal_to(9).
# with_message(/is invalid/) }
def ensure_length_of(attr)
EnsureLengthOfMatcher.new(attr)
end
class EnsureLengthOfMatcher < ValidationMatcher # :nodoc:
include Helpers
2012-04-24 21:33:47 +00:00
def initialize(attribute)
super(attribute)
@options = {}
end
2010-12-15 22:34:19 +00:00
def is_at_least(length)
2012-04-24 21:33:47 +00:00
@options[:minimum] = length
2010-12-15 22:34:19 +00:00
@short_message ||= :too_short
self
end
def is_at_most(length)
2012-04-24 21:33:47 +00:00
@options[:maximum] = length
2010-12-15 22:34:19 +00:00
@long_message ||= :too_long
self
end
def is_equal_to(length)
2012-04-24 21:33:47 +00:00
@options[:minimum] = length
@options[:maximum] = length
2010-12-15 22:34:19 +00:00
@short_message ||= :wrong_length
self
end
def with_short_message(message)
2012-04-24 21:33:47 +00:00
if message
@short_message = message
end
2010-12-15 22:34:19 +00:00
self
end
alias_method :with_message, :with_short_message
def with_long_message(message)
2012-04-24 21:33:47 +00:00
if message
@long_message = message
end
2010-12-15 22:34:19 +00:00
self
end
def description
description = "ensure #{@attribute} has a length "
2012-04-24 21:33:47 +00:00
if @options.key?(:minimum) && @options.key?(:maximum)
if @options[:minimum] == @options[:maximum]
description << "of exactly #{@options[:minimum]}"
2010-12-15 22:34:19 +00:00
else
2012-04-24 21:33:47 +00:00
description << "between #{@options[:minimum]} and #{@options[:maximum]}"
2010-12-15 22:34:19 +00:00
end
else
2012-04-24 21:33:47 +00:00
description << "of at least #{@options[:minimum]}" if @options[:minimum]
description << "of at most #{@options[:maximum]}" if @options[:maximum]
2010-12-15 22:34:19 +00:00
end
description
end
def matches?(subject)
super(subject)
translate_messages!
lower_bound_matches? && upper_bound_matches?
2010-12-15 22:34:19 +00:00
end
private
def translate_messages!
if Symbol === @short_message
@short_message = default_error_message(@short_message,
:model_name => @subject.class.to_s.underscore,
:attribute => @attribute,
2012-04-24 21:33:47 +00:00
:count => @options[:minimum])
2010-12-15 22:34:19 +00:00
end
if Symbol === @long_message
@long_message = default_error_message(@long_message,
:model_name => @subject.class.to_s.underscore,
:attribute => @attribute,
2012-04-24 21:33:47 +00:00
:count => @options[:maximum])
2010-12-15 22:34:19 +00:00
end
end
def lower_bound_matches?
disallows_lower_length? && allows_minimum_length?
end
def upper_bound_matches?
disallows_higher_length? && allows_maximum_length?
end
2012-04-24 21:33:47 +00:00
def disallows_lower_length?
if @options.key?(:minimum)
@options[:minimum] == 0 ||
disallows_length_of?(@options[:minimum] - 1, @short_message)
else
true
end
2010-12-15 22:34:19 +00:00
end
2012-04-24 21:33:47 +00:00
def disallows_higher_length?
if @options.key?(:maximum)
disallows_length_of?(@options[:maximum] + 1, @long_message)
else
true
end
2010-12-15 22:34:19 +00:00
end
2012-04-24 21:33:47 +00:00
def allows_minimum_length?
if @options.key?(:minimum)
allows_length_of?(@options[:minimum], @short_message)
else
true
end
2010-12-15 22:34:19 +00:00
end
2012-04-24 21:33:47 +00:00
def allows_maximum_length?
if @options.key?(:maximum)
allows_length_of?(@options[:maximum], @long_message)
else
true
end
2010-12-15 22:34:19 +00:00
end
2012-04-24 21:33:47 +00:00
def allows_length_of?(length, message)
allows_value_of(string_of_length(length), message)
2010-12-15 22:34:19 +00:00
end
2012-04-24 21:33:47 +00:00
def disallows_length_of?(length, message)
disallows_value_of(string_of_length(length), message)
2010-12-15 22:34:19 +00:00
end
def string_of_length(length)
'x' * length
end
end
end
end
end