Merge branch 'between'

This commit is contained in:
Adam Meehan 2009-01-01 20:30:22 +11:00
commit a7c6e37333
6 changed files with 283 additions and 133 deletions

View File

@ -64,6 +64,7 @@ the valid range of dates or times allowed
:on_or_before - Attribute must be equal to or before this value to be valid
:after - Attribute must be after this value to be valid
:on_or_after - Attribute must be equal to or after this value to be valid
:between - Attribute must be between the values to be valid
Regular validation options:
:allow_nil - Allow a nil value to be valid
@ -79,6 +80,7 @@ the valid range of dates or times allowed
:on_or_before_message
:after_message
:on_or_after_message
:between_message
The temporal restrictions can take 4 different value types:
@ -86,6 +88,7 @@ The temporal restrictions can take 4 different value types:
* Date, Time, or DateTime object value
* Proc or lambda object
* A symbol matching the method name in the model
* Between option takes an array of two values or a range
When an attribute value is compared to temporal restrictions, they are compared as
the same type as the validation method type. So using validates_date means all
@ -266,7 +269,8 @@ For Rails 2.0/2.1:
:before => "must be before %s",
:on_or_before => "must be on or before %s",
:after => "must be after %s",
:on_or_after => "must be on or after %s"
:on_or_after => "must be on or after %s",
:between => "must be between %s and %s"
)
Where %s is the interpolation value for the restriction.
@ -279,6 +283,7 @@ Rails 2.2+ using the I18n system to define new defaults:
messages:
on_or_before: "must be equal to or before {{restriction}}"
on_or_after: "must be equal to or after {{restriction}}"
between: "must be between {{earliest}} and {{latest}}"
The {{restriction}} signifies where the interpolation value for the restriction
will be inserted.

View File

@ -9,3 +9,4 @@ en:
on_or_before: "must be on or before {{restriction}}"
after: "must be after {{restriction}}"
on_or_after: "must be on or after {{restriction}}"
between: "must be between {{earliest}} and {{latest}}"

View File

@ -2,120 +2,156 @@ module Spec
module Rails
module Matchers
class ValidateTimeliness
cattr_accessor :test_values
@@test_values = {
VALIDITY_TEST_VALUES = {
:date => {:pass => '2000-01-01', :fail => '2000-01-32'},
:time => {:pass => '12:00', :fail => '25:00'},
:datetime => {:pass => '2000-01-01 00:00:00', :fail => '2000-01-32 00:00:00'}
}
OPTION_TEST_SETTINGS = {
:before => { :method => :-, :modify_on => :valid },
:after => { :method => :+, :modify_on => :valid },
:on_or_before => { :method => :+, :modify_on => :invalid },
:on_or_after => { :method => :-, :modify_on => :invalid }
}
def initialize(attribute, options)
@expected, @options = attribute, options
@validator = ValidatesTimeliness::Validator.new(options)
compile_error_messages
end
def compile_error_messages
messages = validator.send(:error_messages)
@messages = messages.inject({}) {|h, (k, v)| h[k] = v.gsub(/ (\%s|\{\{\w*\}\})/, ''); h }
end
def matches?(record)
@record = record
type = options[:type]
@type = options[:type]
invalid_value = @@test_values[type][:fail]
valid_value = parse_and_cast(@@test_values[type][:pass])
valid = error_matching(invalid_value, /#{messages["invalid_#{type}".to_sym]}/) &&
no_error_matching(valid_value, /#{messages["invalid_#{type}".to_sym]}/)
valid = test_validity
valid = test_option(:before, :-) if options[:before] && valid
valid = test_option(:after, :+) if options[:after] && valid
valid = test_option(:before) if @options[:before] && valid
valid = test_option(:after) if @options[:after] && valid
valid = test_option(:on_or_before, :+, :modify_on => :invalid) if options[:on_or_before] && valid
valid = test_option(:on_or_after, :-, :modify_on => :invalid) if options[:on_or_after] && valid
valid = test_option(:on_or_before) if @options[:on_or_before] && valid
valid = test_option(:on_or_after) if @options[:on_or_after] && valid
valid = test_between if @options[:between] && valid
return valid
end
def failure_message
"expected model to validate #{options[:type]} attribute #{expected.inspect} with #{last_failure}"
"expected model to validate #{@type} attribute #{@expected.inspect} with #{@last_failure}"
end
def negative_failure_message
"expected not to validate #{options[:type]} attribute #{expected.inspect}"
"expected not to validate #{@type} attribute #{@expected.inspect}"
end
def description
"have validated #{options[:type]} attribute #{expected.inspect}"
"have validated #{@type} attribute #{@expected.inspect}"
end
private
attr_reader :actual, :expected, :record, :options, :messages, :last_failure, :validator
def test_option(option, modifier, settings={})
settings.reverse_merge!(:modify_on => :valid)
boundary = parse_and_cast(options[option])
def test_validity
invalid_value = VALIDITY_TEST_VALUES[@type][:fail]
valid_value = parse_and_cast(VALIDITY_TEST_VALUES[@type][:pass])
error_matching(invalid_value, "invalid_#{@type}".to_sym) &&
no_error_matching(valid_value, "invalid_#{@type}".to_sym)
end
def test_option(option)
settings = OPTION_TEST_SETTINGS[option]
boundary = parse_and_cast(@options[option])
method = settings[:method]
valid_value, invalid_value = if settings[:modify_on] == :valid
[ boundary.send(modifier, 1), boundary ]
[ boundary.send(method, 1), boundary ]
else
[ boundary, boundary.send(modifier, 1) ]
[ boundary, boundary.send(method, 1) ]
end
message = messages[option]
error_matching(invalid_value, /#{message}/) &&
no_error_matching(valid_value, /#{message}/)
error_matching(invalid_value, option) &&
no_error_matching(valid_value, option)
end
def test_before
before = parse_and_cast(@options[:before])
error_matching(before - 1, :before) &&
no_error_matching(before, :before)
end
def test_between
between = parse_and_cast(@options[:between])
error_matching(between.first - 1, :between) &&
error_matching(between.last + 1, :between) &&
no_error_matching(between.first, :between) &&
no_error_matching(between.last, :between)
end
def parse_and_cast(value)
value = validator.send(:restriction_value, value, record)
validator.send(:type_cast_value, value)
value = @validator.send(:restriction_value, value, @record)
@validator.send(:type_cast_value, value)
end
def error_matching(value, match)
record.send("#{expected}=", value)
record.valid?
errors = record.errors.on(expected)
pass = [ errors ].flatten.any? {|error| match === error }
@last_failure = "error matching #{match.inspect} when value is #{format_value(value)}" unless pass
def error_matching(value, option)
match = error_message_for(option)
@record.send("#{@expected}=", value)
@record.valid?
errors = @record.errors.on(@expected)
pass = [ errors ].flatten.any? {|error| /#{match}/ === error }
@last_failure = "error matching '#{match}' when value is #{format_value(value)}" unless pass
pass
end
def no_error_matching(value, match)
pass = !error_matching(value, match)
@last_failure = "no error matching #{match.inspect} when value is #{format_value(value)}" unless pass
def no_error_matching(value, option)
pass = !error_matching(value, option)
unless pass
error = error_message_for(option)
@last_failure = "no error matching '#{error}' when value is #{format_value(value)}"
end
pass
end
def error_message_for(option)
msg = @validator.send(:error_messages)[option]
restriction = @validator.send(:restriction_value, @validator.configuration[option], @record)
if restriction
restriction = [restriction] unless restriction.is_a?(Array)
restriction.map! {|r| @validator.send(:type_cast_value, r) }
interpolate = @validator.send(:interpolation_values, option, restriction )
if defined?(I18n)
msg = @record.errors.generate_message(@expected, option, interpolate)
else
msg = msg % interpolate
end
end
msg
end
def format_value(value)
return value if value.is_a?(String)
value.strftime(ValidatesTimeliness::Validator.error_value_formats[options[:type]])
value.strftime(ValidatesTimeliness::Validator.error_value_formats[@type])
end
end
def validate_date(attribute, options={})
options[:type] = :date
validate_timeliness_of(attribute, options)
ValidateTimeliness.new(attribute, options)
end
def validate_time(attribute, options={})
options[:type] = :time
validate_timeliness_of(attribute, options)
ValidateTimeliness.new(attribute, options)
end
def validate_datetime(attribute, options={})
options[:type] = :datetime
validate_timeliness_of(attribute, options)
end
private
def validate_timeliness_of(attribute, options={})
ValidateTimeliness.new(attribute, options)
end
end
end
end

View File

@ -11,6 +11,14 @@ module ValidatesTimeliness
:datetime => '%Y-%m-%d %H:%M:%S'
}
RESTRICTION_METHODS = {
:before => :<,
:after => :>,
:on_or_before => :<=,
:on_or_after => :>=,
:between => lambda {|v, r| (r.first..r.last).include?(v) }
}
attr_reader :configuration, :type
def initialize(configuration)
@ -40,21 +48,17 @@ module ValidatesTimeliness
end
def validate_restrictions(record, attr_name, value)
restriction_methods = {:before => '<', :after => '>', :on_or_before => '<=', :on_or_after => '>='}
display = self.class.error_value_formats[type]
value = type_cast_value(value)
restriction_methods.each do |option, method|
RESTRICTION_METHODS.each do |option, method|
next unless restriction = configuration[option]
begin
compare = restriction_value(restriction, record)
next if compare.nil?
compare = type_cast_value(compare)
restriction = restriction_value(restriction, record)
next if restriction.nil?
restriction = type_cast_value(restriction)
unless value.send(method, compare)
add_error(record, attr_name, option, :restriction => compare.strftime(display))
unless evaluate_restriction(restriction, value, method)
add_error(record, attr_name, option, interpolation_values(option, restriction))
end
rescue
unless self.class.ignore_restriction_errors
@ -63,15 +67,41 @@ module ValidatesTimeliness
end
end
end
def interpolation_values(option, restriction)
format = self.class.error_value_formats[type]
restriction = [restriction] unless restriction.is_a?(Array)
if defined?(I18n)
message = custom_error_messages[option] || I18n.translate('activerecord.errors.messages')[option]
subs = message.scan(/\{\{([^\}]*)\}\}/)
interpolations = {}
subs.each_with_index {|s, i| interpolations[s[0].to_sym] = restriction[i].strftime(format) }
interpolations
else
restriction.map {|r| r.strftime(format) }
end
end
def evaluate_restriction(restriction, value, comparator)
return true if restriction.nil?
case comparator
when Symbol
value.send(comparator, restriction)
when Proc
comparator.call(value, restriction)
end
end
def add_error(record, attr_name, message, interpolate={})
def add_error(record, attr_name, message, interpolate=nil)
if defined?(I18n)
# use i18n support in AR for message or use custom message passed to validation method
custom = custom_error_messages[message]
record.errors.add(attr_name, custom || message, interpolate)
record.errors.add(attr_name, custom || message, interpolate || {})
else
message = error_messages[message] if message.is_a?(Symbol)
message = message % interpolate.values unless interpolate.empty?
message = message % interpolate
record.errors.add(attr_name, message)
end
end
@ -83,7 +113,12 @@ module ValidatesTimeliness
def custom_error_messages
return @custom_error_messages if defined?(@custom_error_messages)
@custom_error_messages = configuration.inject({}) {|h, (k, v)| h[$1.to_sym] = v if k.to_s =~ /(.*)_message$/;h }
@custom_error_messages = configuration.inject({}) {|msgs, (k, v)|
if md = /(.*)_message$/.match(k.to_s)
msgs[md[0].to_sym] = v
end
msgs
}
end
def restriction_value(restriction, record)
@ -94,13 +129,20 @@ module ValidatesTimeliness
restriction_value(record.send(restriction), record)
when Proc
restriction_value(restriction.call(record), record)
when Array
restriction.map {|r| restriction_value(r, record) }.sort
when Range
restriction_value([restriction.first, restriction.last], record)
else
record.class.parse_date_time(restriction, type, false)
end
end
def type_cast_value(value)
case type
if value.is_a?(Array)
value.map {|v| type_cast_value(v) }
else
case type
when :time
value.to_dummy_time
when :date
@ -109,10 +151,11 @@ module ValidatesTimeliness
if value.is_a?(DateTime) || value.is_a?(Time)
value.to_time
else
value.to_time(ValidatesTimelines.default_timezone)
value.to_time(ValidatesTimeliness.default_timezone)
end
else
nil
end
end
end

View File

@ -6,13 +6,17 @@ end
class WithValidation < Person
validates_date :birth_date,
:before => '2000-01-10', :after => '2000-01-01',
:on_or_before => '2000-01-09', :on_or_after => '2000-01-02'
:on_or_before => '2000-01-09', :on_or_after => '2000-01-02',
:between => ['2000-01-01', '2000-01-03']
validates_time :birth_time,
:before => '23:00', :after => '09:00',
:on_or_before => '22:00', :on_or_after => '10:00'
:on_or_before => '22:00', :on_or_after => '10:00',
:between => ['09:00', '17:00']
validates_datetime :birth_date_and_time,
:before => '2000-01-10 23:00', :after => '2000-01-01 09:00',
:on_or_before => '2000-01-09 23:00', :on_or_after => '2000-01-02 09:00'
:on_or_before => '2000-01-09 23:00', :on_or_after => '2000-01-02 09:00',
:between => ['2000-01-01 09:00', '2000-01-01 17:00']
end
@ -27,20 +31,21 @@ end
describe "ValidateTimeliness matcher" do
attr_accessor :no_validation, :with_validation
@@attribute_for_type = { :date => :birth_date, :time => :birth_time, :datetime => :birth_date_and_time }
before do
@no_validation = NoValidation.new
@with_validation = WithValidation.new
end
[:date, :time, :datetime].each do |type|
attribute = type == :datetime ? :date_and_time : type
it "should report that #{type} is validated" do
with_validation.should self.send("validate_#{type}", "birth_#{attribute}".to_sym)
with_validation.should self.send("validate_#{type}", attribute_for_type(type))
end
it "should report that #{type} is not validated" do
no_validation.should_not self.send("validate_#{type}", "birth_#{attribute}".to_sym)
no_validation.should_not self.send("validate_#{type}", attribute_for_type(type))
end
end
@ -52,18 +57,17 @@ describe "ValidateTimeliness matcher" do
}
[:date, :time, :datetime].each do |type|
attribute = type == :datetime ? :date_and_time : type
it "should report that #{type} is validated" do
with_validation.should self.send("validate_#{type}", "birth_#{attribute}", :before => test_values[type][0])
with_validation.should self.send("validate_#{type}", attribute_for_type(type), :before => test_values[type][0])
end
it "should report that #{type} is not validated when option value is incorrect" do
with_validation.should_not self.send("validate_#{type}", "birth_#{attribute}", :before => test_values[type][1])
with_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :before => test_values[type][1])
end
it "should report that #{type} is not validated with option" do
no_validation.should_not self.send("validate_#{type}", "birth_#{attribute}", :before => test_values[type][0])
no_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :before => test_values[type][0])
end
end
end
@ -76,18 +80,17 @@ describe "ValidateTimeliness matcher" do
}
[:date, :time, :datetime].each do |type|
attribute = type == :datetime ? :date_and_time : type
it "should report that #{type} is validated" do
with_validation.should self.send("validate_#{type}", "birth_#{attribute}", :after => test_values[type][0])
with_validation.should self.send("validate_#{type}", attribute_for_type(type), :after => test_values[type][0])
end
it "should report that #{type} is not validated when option value is incorrect" do
with_validation.should_not self.send("validate_#{type}", "birth_#{attribute}", :after => test_values[type][1])
with_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :after => test_values[type][1])
end
it "should report that #{type} is not validated with option" do
no_validation.should_not self.send("validate_#{type}", "birth_#{attribute}", :after => test_values[type][0])
no_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :after => test_values[type][0])
end
end
end
@ -100,18 +103,17 @@ describe "ValidateTimeliness matcher" do
}
[:date, :time, :datetime].each do |type|
attribute = type == :datetime ? :date_and_time : type
it "should report that #{type} is validated" do
with_validation.should self.send("validate_#{type}", "birth_#{attribute}", :on_or_before => test_values[type][0])
with_validation.should self.send("validate_#{type}", attribute_for_type(type), :on_or_before => test_values[type][0])
end
it "should report that #{type} is not validated when option value is incorrect" do
with_validation.should_not self.send("validate_#{type}", "birth_#{attribute}", :on_or_before => test_values[type][1])
with_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :on_or_before => test_values[type][1])
end
it "should report that #{type} is not validated with option" do
no_validation.should_not self.send("validate_#{type}", "birth_#{attribute}", :on_or_before => test_values[type][0])
no_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :on_or_before => test_values[type][0])
end
end
end
@ -124,22 +126,44 @@ describe "ValidateTimeliness matcher" do
}
[:date, :time, :datetime].each do |type|
attribute = type == :datetime ? :date_and_time : type
it "should report that #{type} is validated" do
with_validation.should self.send("validate_#{type}", "birth_#{attribute}", :on_or_after => test_values[type][0])
with_validation.should self.send("validate_#{type}", attribute_for_type(type), :on_or_after => test_values[type][0])
end
it "should report that #{type} is not validated when option value is incorrect" do
with_validation.should_not self.send("validate_#{type}", "birth_#{attribute}", :on_or_after => test_values[type][1])
with_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :on_or_after => test_values[type][1])
end
it "should report that #{type} is not validated with option" do
no_validation.should_not self.send("validate_#{type}", "birth_#{attribute}", :on_or_after => test_values[type][0])
no_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :on_or_after => test_values[type][0])
end
end
end
describe "between option" do
test_values = {
:date => [ ['2000-01-01', '2000-01-03'], ['2000-01-01', '2000-01-04'] ],
:time => [ ['09:00', '17:00'], ['09:00', '17:01'] ],
:datetime => [ ['2000-01-01 09:00', '2000-01-01 17:00'], ['2000-01-01 09:00', '2000-01-01 17:01'] ]
}
[:date, :time, :datetime].each do |type|
it "should report that #{type} is validated" do
with_validation.should self.send("validate_#{type}", attribute_for_type(type), :between => test_values[type][0])
end
it "should report that #{type} is not validated when option value is incorrect" do
with_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :between => test_values[type][1])
end
it "should report that #{type} is not validated with option" do
no_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :between => test_values[type][0])
end
end
end
describe "custom messages" do
before do
@ -175,4 +199,8 @@ describe "ValidateTimeliness matcher" do
end
end
def attribute_for_type(type)
@@attribute_for_type[type.to_sym]
end
end

View File

@ -43,6 +43,25 @@ describe ValidatesTimeliness::Validator do
restriction_value(lambda {"2007-01-01 12:00"}, :datetime).should be_kind_of(Time)
end
it "should return array of Time objects when restriction is array of Time objects" do
time1, time2 = Time.now, 1.day.ago
restriction_value([time1, time2], :datetime).should == [time2, time1]
end
it "should return array of Time objects when restriction is array of strings" do
time1, time2 = "2000-01-02", "2000-01-01"
restriction_value([time1, time2], :datetime).should == [Person.parse_date_time(time2, :datetime), Person.parse_date_time(time1, :datetime)]
end
it "should return array of Time objects when restriction is Range of Time objects" do
time1, time2 = Time.now, 1.day.ago
restriction_value(time1..time2, :datetime).should == [time2, time1]
end
it "should return array of Time objects when restriction is Range of time strings" do
time1, time2 = "2000-01-02", "2000-01-01"
restriction_value(time1..time2, :datetime).should == [Person.parse_date_time(time2, :datetime), Person.parse_date_time(time1, :datetime)]
end
def restriction_value(restriction, type)
configure_validator(:type => type)
validator.send(:restriction_value, restriction, person)
@ -212,83 +231,101 @@ describe ValidatesTimeliness::Validator do
end
end
describe "instance with on_or_before and on_or_after restrictions" do
describe "instance with between restriction" do
describe "for datetime type" do
before do
configure_validator(:on_or_before => Time.now.at_midnight, :on_or_after => 1.day.ago)
configure_validator(:between => [1.day.ago.at_midnight, 1.day.from_now.at_midnight])
end
it "should have error when value is past :on_or_before restriction" do
validate_with(:birth_date_and_time, Time.now.at_midnight + 1)
should_have_error(:birth_date_and_time, :on_of_before)
it "should have error when value is before earlist :between restriction" do
validate_with(:birth_date_and_time, 2.days.ago)
should_have_error(:birth_date_and_time, :between)
end
it "should be valid when value is equal to :on_or_before restriction" do
validate_with(:birth_date_and_time, Time.now.at_midnight)
should_have_no_error(:birth_date_and_time, :on_of_before)
it "should have error when value is after latest :between restriction" do
validate_with(:birth_date_and_time, 2.days.from_now)
should_have_error(:birth_date_and_time, :between)
end
it "should have error when value is before :on_or_after restriction" do
validate_with(:birth_date_and_time, 1.days.ago - 1)
should_have_error(:birth_date_and_time, :on_of_after)
it "should be valid when value is equal to earliest :between restriction" do
validate_with(:birth_date_and_time, 1.day.ago.at_midnight)
should_have_no_error(:birth_date_and_time, :between)
end
it "should be valid when value is value equal to :on_or_after restriction" do
validate_with(:birth_date_and_time, 1.day.ago)
should_have_no_error(:birth_date_and_time, :on_of_after)
it "should be valid when value is equal to latest :between restriction" do
validate_with(:birth_date_and_time, 1.day.from_now.at_midnight)
should_have_no_error(:birth_date_and_time, :between)
end
it "should allow a range for between restriction" do
configure_validator(:type => :datetime, :between => (1.day.ago.at_midnight)..(1.day.from_now.at_midnight))
validate_with(:birth_date_and_time, 1.day.from_now.at_midnight)
should_have_no_error(:birth_date_and_time, :between)
end
end
describe "for date type" do
before :each do
configure_validator(:on_or_before => 1.day.from_now, :on_or_after => 1.day.ago, :type => :date)
before do
configure_validator(:type => :date, :between => [1.day.ago.to_date, 1.day.from_now.to_date])
end
it "should have error when value is past :on_or_before restriction" do
validate_with(:birth_date, 2.days.from_now)
should_have_error(:birth_date, :on_or_before)
it "should have error when value is before earlist :between restriction" do
validate_with(:birth_date, 2.days.ago.to_date)
should_have_error(:birth_date, :between)
end
it "should have error when value is before :on_or_after restriction" do
validate_with(:birth_date, 2.days.ago)
should_have_error(:birth_date, :on_or_after)
it "should have error when value is after latest :between restriction" do
validate_with(:birth_date, 2.days.from_now.to_date)
should_have_error(:birth_date, :between)
end
it "should be valid when value is equal to :on_or_before restriction" do
validate_with(:birth_date, 1.day.from_now)
should_have_no_error(:birth_date, :on_or_before)
it "should be valid when value is equal to earliest :between restriction" do
validate_with(:birth_date, 1.day.ago.to_date)
should_have_no_error(:birth_date, :between)
end
it "should be valid when value value is equal to :on_or_after restriction" do
validate_with(:birth_date, 1.day.ago)
should_have_no_error(:birth_date, :on_or_before)
it "should be valid when value is equal to latest :between restriction" do
validate_with(:birth_date, 1.day.from_now.to_date)
should_have_no_error(:birth_date, :between)
end
it "should allow a range for between restriction" do
configure_validator(:type => :date, :between => (1.day.ago.to_date)..(1.day.from_now.to_date))
validate_with(:birth_date, 1.day.from_now.to_date)
should_have_no_error(:birth_date, :between)
end
end
describe "for time type" do
before :each do
configure_validator(:on_or_before => "23:00", :on_or_after => "06:00", :type => :time)
before do
configure_validator(:type => :time, :between => ["09:00", "17:00"])
end
it "should have error when value is past :on_or_before restriction" do
validate_with(:birth_time, "23:01")
should_have_error(:birth_time, :on_or_before)
it "should have error when value is before earlist :between restriction" do
validate_with(:birth_time, "08:59")
should_have_error(:birth_time, :between)
end
it "should have error when value is before :on_or_after restriction" do
validate_with(:birth_time, "05:59")
should_have_error(:birth_time, :on_or_after)
it "should have error when value is after latest :between restriction" do
validate_with(:birth_time, "17:01")
should_have_error(:birth_time, :between)
end
it "should be valid when value is on boundary of :on_or_before restriction" do
validate_with(:birth_time, "23:00")
should_have_no_error(:birth_time, :on_or_before)
it "should be valid when value is equal to earliest :between restriction" do
validate_with(:birth_time, "09:00")
should_have_no_error(:birth_time, :between)
end
it "should be valid when value is on boundary of :on_or_after restriction" do
validate_with(:birth_time, "06:00")
should_have_no_error(:birth_time, :on_or_after)
it "should be valid when value is equal to latest :between restriction" do
validate_with(:birth_time, "17:00")
should_have_no_error(:birth_time, :between)
end
it "should allow a range for between restriction" do
configure_validator(:type => :time, :between => "09:00".."17:00")
validate_with(:birth_time, "17:00")
should_have_no_error(:birth_time, :between)
end
end
end
@ -433,6 +470,6 @@ describe ValidatesTimeliness::Validator do
def error_messages
return @error_messages if defined?(@error_messages)
messages = validator.send(:error_messages)
@error_messages = messages.inject({}) {|h, (k, v)| h[k] = v.gsub(/ (\%s|\{\{\w*\}\})/, ''); h }
@error_messages = messages.inject({}) {|h, (k, v)| h[k] = v.sub(/ (\%s|\{\{\w*\}\}).*/, ''); h }
end
end