2010-12-15 17:34:19 -05:00
|
|
|
module Shoulda # :nodoc:
|
|
|
|
module Matchers
|
2011-05-06 07:51:12 -04:00
|
|
|
module ActiveModel # :nodoc:
|
2012-06-04 11:56:47 -04:00
|
|
|
# Ensure that the attribute is numeric.
|
2010-12-15 17:34:19 -05:00
|
|
|
#
|
|
|
|
# Options:
|
|
|
|
# * <tt>with_message</tt> - value the test expects to find in
|
|
|
|
# <tt>errors.on(:attribute)</tt>. Regexp or string. Defaults to the
|
|
|
|
# translation for <tt>:not_a_number</tt>.
|
2011-10-26 22:21:06 -04:00
|
|
|
# * <tt>only_integer</tt> - allows only integer values
|
2010-12-15 17:34:19 -05:00
|
|
|
#
|
2011-10-26 22:21:06 -04:00
|
|
|
# Examples:
|
|
|
|
# it { should validate_numericality_of(:price) }
|
|
|
|
# it { should validate_numericality_of(:age).only_integer }
|
2010-12-15 17:34:19 -05:00
|
|
|
#
|
|
|
|
def validate_numericality_of(attr)
|
|
|
|
ValidateNumericalityOfMatcher.new(attr)
|
|
|
|
end
|
|
|
|
|
2012-10-16 13:45:06 -04:00
|
|
|
class ValidateNumericalityOfMatcher
|
2012-04-24 18:00:26 -04:00
|
|
|
def initialize(attribute)
|
2012-10-16 13:45:06 -04:00
|
|
|
@attribute = attribute
|
2012-04-24 18:00:26 -04:00
|
|
|
@options = {}
|
2012-10-16 13:45:06 -04:00
|
|
|
@submatchers = []
|
|
|
|
|
|
|
|
add_disallow_value_matcher
|
2012-04-24 18:00:26 -04:00
|
|
|
end
|
2011-10-26 22:21:06 -04:00
|
|
|
|
|
|
|
def only_integer
|
2012-10-16 13:45:06 -04:00
|
|
|
only_integer_matcher = OnlyIntegerMatcher.new(@attribute)
|
|
|
|
add_submatcher(only_integer_matcher)
|
|
|
|
|
2011-10-26 22:21:06 -04:00
|
|
|
self
|
|
|
|
end
|
|
|
|
|
2010-12-15 17:34:19 -05:00
|
|
|
def with_message(message)
|
2012-10-16 13:45:06 -04:00
|
|
|
@expected_message = message
|
2010-12-15 17:34:19 -05:00
|
|
|
self
|
|
|
|
end
|
|
|
|
|
|
|
|
def matches?(subject)
|
2012-10-16 13:45:06 -04:00
|
|
|
@subject = subject
|
|
|
|
set_expected_message_on_submatchers
|
|
|
|
submatchers_match?
|
2010-12-15 17:34:19 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def description
|
2012-10-16 13:45:06 -04:00
|
|
|
"only allow #{allowed_types} values for #{@attribute}"
|
|
|
|
end
|
|
|
|
|
|
|
|
def failure_message
|
|
|
|
@disallow_value_matcher.failure_message
|
2010-12-15 17:34:19 -05:00
|
|
|
end
|
|
|
|
|
2012-03-30 10:36:55 -04:00
|
|
|
private
|
|
|
|
|
2012-10-16 13:45:06 -04:00
|
|
|
def add_disallow_value_matcher
|
|
|
|
@disallow_value_matcher = DisallowValueMatcher.new('abcd').for(@attribute)
|
|
|
|
add_submatcher(@disallow_value_matcher)
|
2012-04-03 20:20:50 -04:00
|
|
|
end
|
|
|
|
|
2012-10-16 13:45:06 -04:00
|
|
|
def add_submatcher(submatcher)
|
|
|
|
@submatchers << submatcher
|
2011-10-26 22:21:06 -04:00
|
|
|
end
|
|
|
|
|
2012-10-16 13:45:06 -04:00
|
|
|
def set_expected_message_on_submatchers
|
2011-10-26 22:21:06 -04:00
|
|
|
message = @expected_message || :not_a_number
|
2012-10-16 13:45:06 -04:00
|
|
|
@submatchers.each { |matcher| matcher.with_message(message) }
|
|
|
|
end
|
|
|
|
|
|
|
|
def submatchers_match?
|
|
|
|
@submatchers.all? { |matcher| matcher.matches?(@subject) }
|
|
|
|
end
|
|
|
|
|
|
|
|
def allowed_types
|
|
|
|
allowed = ["numeric"] + submatcher_allowed_types
|
|
|
|
allowed.join(", ")
|
|
|
|
end
|
|
|
|
|
|
|
|
def submatcher_allowed_types
|
|
|
|
@submatchers.map(&:allowed_types).reject { |type| type.empty? }
|
2012-03-30 10:36:55 -04:00
|
|
|
end
|
|
|
|
end
|
2010-12-15 17:34:19 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|