added :equal_to and :ignore_usec options. the later is for ignore microsecond value in datetime restrictions

This commit is contained in:
Adam Meehan
2009-03-19 20:49:06 +11:00
parent eecef62de4
commit d1ee94248b
4 changed files with 81 additions and 7 deletions

View File

@@ -63,6 +63,7 @@ The validation methods take the usual options plus some specific ones to restric
the valid range of dates or times allowed the valid range of dates or times allowed
Temporal options (or restrictions): Temporal options (or restrictions):
:equal_to - Attribute must be equal to value to be valid
:before - Attribute must be before this value to be valid :before - Attribute must be before this value to be valid
:on_or_before - Attribute must be equal to or before this value to be valid :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 :after - Attribute must be after this value to be valid
@@ -78,11 +79,13 @@ Regular validation options:
Special options: Special options:
:with_time - Validate a date attribute value combined with a time value against any temporal restrictions :with_time - Validate a date attribute value combined with a time value against any temporal restrictions
:with_date - Validate a time attribute value combined with a date value against any temporal restrictions :with_date - Validate a time attribute value combined with a date value against any temporal restrictions
:ignore_usec - Ignores microsecond value on datetime restrictions
Message options: - Use these to override the default error messages Message options: - Use these to override the default error messages
:invalid_date_message :invalid_date_message
:invalid_time_message :invalid_time_message
:invalid_datetime_message :invalid_datetime_message
:equal_to_message
:before_message :before_message
:on_or_before_message :on_or_before_message
:after_message :after_message

View File

@@ -5,6 +5,7 @@ en:
invalid_date: "is not a valid date" invalid_date: "is not a valid date"
invalid_time: "is not a valid time" invalid_time: "is not a valid time"
invalid_datetime: "is not a valid datetime" invalid_datetime: "is not a valid datetime"
equal_to: "must be equal to {{restriction}}"
before: "must be before {{restriction}}" before: "must be before {{restriction}}"
on_or_before: "must be on or before {{restriction}}" on_or_before: "must be on or before {{restriction}}"
after: "must be after {{restriction}}" after: "must be after {{restriction}}"

View File

@@ -12,6 +12,7 @@ module ValidatesTimeliness
} }
RESTRICTION_METHODS = { RESTRICTION_METHODS = {
:equal_to => :==,
:before => :<, :before => :<,
:after => :>, :after => :>,
:on_or_before => :<=, :on_or_before => :<=,
@@ -20,14 +21,15 @@ module ValidatesTimeliness
} }
VALID_OPTIONS = [ VALID_OPTIONS = [
:on, :if, :unless, :allow_nil, :empty, :allow_blank, :blank, :with_time, :with_date, :on, :if, :unless, :allow_nil, :empty, :allow_blank, :blank,
:with_time, :with_date, :ignore_usec,
:invalid_time_message, :invalid_date_message, :invalid_datetime_message :invalid_time_message, :invalid_date_message, :invalid_datetime_message
] + RESTRICTION_METHODS.keys.map {|option| [option, "#{option}_message".to_sym] }.flatten ] + RESTRICTION_METHODS.keys.map {|option| [option, "#{option}_message".to_sym] }.flatten
attr_reader :configuration, :type attr_reader :configuration, :type
def initialize(configuration) def initialize(configuration)
defaults = { :on => :save, :type => :datetime, :allow_nil => false, :allow_blank => false } defaults = { :on => :save, :type => :datetime, :allow_nil => false, :allow_blank => false, :ignore_usec => false }
@configuration = defaults.merge(configuration) @configuration = defaults.merge(configuration)
@type = @configuration.delete(:type) @type = @configuration.delete(:type)
validate_options(@configuration) validate_options(@configuration)
@@ -58,7 +60,7 @@ module ValidatesTimeliness
combine_date_and_time(value, record) combine_date_and_time(value, record)
else else
restriction_type = type restriction_type = type
self.class.type_cast_value(value, type) self.class.type_cast_value(value, type, @configuration[:ignore_usec])
end end
return if value.nil? return if value.nil?
@@ -67,7 +69,7 @@ module ValidatesTimeliness
begin begin
restriction = self.class.evaluate_option_value(restriction, restriction_type, record) restriction = self.class.evaluate_option_value(restriction, restriction_type, record)
next if restriction.nil? next if restriction.nil?
restriction = self.class.type_cast_value(restriction, restriction_type) restriction = self.class.type_cast_value(restriction, restriction_type, @configuration[:ignore_usec])
unless evaluate_restriction(restriction, value, method) unless evaluate_restriction(restriction, value, method)
add_error(record, attr_name, option, interpolation_values(option, restriction)) add_error(record, attr_name, option, interpolation_values(option, restriction))
@@ -171,11 +173,11 @@ module ValidatesTimeliness
end end
end end
def type_cast_value(value, type) def type_cast_value(value, type, ignore_usec=false)
if value.is_a?(Array) if value.is_a?(Array)
value.map {|v| type_cast_value(v, type) } value.map {|v| type_cast_value(v, type, ignore_usec) }
else else
case type value = case type
when :time when :time
value.to_dummy_time value.to_dummy_time
when :date when :date
@@ -189,6 +191,11 @@ module ValidatesTimeliness
else else
nil nil
end end
if ignore_usec && value.is_a?(Time)
::ActiveRecord::Base.send(:make_time, Array(value).reverse[4..9])
else
value
end
end end
end end

View File

@@ -346,6 +346,69 @@ describe ValidatesTimeliness::Validator do
end end
end end
describe "instance with :equal_to restriction" do
describe "for datetime type" do
before do
configure_validator(:equal_to => Time.now)
end
it "should have error when value not equal to :equal_to restriction" do
validate_with(:birth_date_and_time, Time.now + 1)
should_have_error(:birth_date_and_time, :equal_to)
end
it "should have error when value is equal to :equal_to restriction for all values except microscond, and microsecond is not ignored" do
configure_validator(:equal_to => Time.utc(2000, 1, 1, 0, 0, 0, 0), :ignore_usec => false)
validate_with(:birth_date_and_time, Time.utc(2000, 1, 1, 0, 0, 0, 500))
should_have_error(:birth_date_and_time, :equal_to)
end
it "should be valid when value is equal to :equal_to restriction for all values except microscond, and microsecond is ignored" do
configure_validator(:equal_to => Time.utc(2000, 1, 1, 0, 0, 0, 0), :ignore_usec => true)
validate_with(:birth_date_and_time, Time.utc(2000, 1, 1, 0, 0, 0, 500))
should_have_no_error(:birth_date_and_time, :equal_to)
end
it "should be valid when value is equal to :equal_to restriction" do
validate_with(:birth_date_and_time, Time.now)
should_have_no_error(:birth_date_and_time, :equal_to)
end
end
describe "for date type" do
before do
configure_validator(:type => :date, :equal_to => Date.today)
end
it "should have error when value is not equal to :equal_to restriction" do
validate_with(:birth_date, Date.today + 1)
should_have_error(:birth_date, :equal_to)
end
it "should be valid when value is equal to :equal_to restriction" do
validate_with(:birth_date, Date.today)
should_have_no_error(:birth_date, :equal_to)
end
end
describe "for time type" do
before do
configure_validator(:type => :time, :equal_to => "09:00:00")
end
it "should have error when value is not equal to :equal_to restriction" do
validate_with(:birth_time, "09:00:01")
should_have_error(:birth_time, :equal_to)
end
it "should be valid when value is equal to :equal_to restriction" do
validate_with(:birth_time, "09:00:00")
should_have_no_error(:birth_time, :equal_to)
end
end
end
describe "instance with :with_time option" do describe "instance with :with_time option" do
it "should validate date attribute as datetime combining value of :with_time against restrictions " do it "should validate date attribute as datetime combining value of :with_time against restrictions " do