mirror of
https://github.com/ditkrg/validates_timeliness.git
synced 2026-01-25 15:22:58 +00:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6af61917dd | ||
|
|
43e6748cd2 | ||
|
|
760a52a2a4 | ||
|
|
9f1642c730 | ||
|
|
011ea070db | ||
|
|
b632093ce2 | ||
|
|
525b3b9941 | ||
|
|
db8dd9ac99 | ||
|
|
1fdfc23cb8 | ||
|
|
7d3ee4bc1b | ||
|
|
694a4bdd69 | ||
|
|
07359c6157 | ||
|
|
215b3dedfd | ||
|
|
753a63417b | ||
|
|
af923014f5 | ||
|
|
a7c6e37333 | ||
|
|
a14bc306b3 | ||
|
|
a71d6f7945 | ||
|
|
45ab815039 | ||
|
|
c308aaf4a9 | ||
|
|
6584d0f1f0 | ||
|
|
5abaec66ae | ||
|
|
ea5452a604 | ||
|
|
40437c970d | ||
|
|
37bfbfe5e7 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pkg/
|
||||||
11
CHANGELOG
11
CHANGELOG
@@ -1,3 +1,14 @@
|
|||||||
|
= 1.1.2 [2009-01-12]
|
||||||
|
- Fixed bugs
|
||||||
|
- matcher failing for custom error message without interpolation keys using I18n
|
||||||
|
- validator custom error messages not being extracted
|
||||||
|
|
||||||
|
= 1.1.1 [2009-01-03]
|
||||||
|
- Fixed bug in matcher for options local variable
|
||||||
|
|
||||||
|
= 1.1.0 [2009-01-01]
|
||||||
|
- Added between option
|
||||||
|
|
||||||
= 1.0.0 [2008-12-06]
|
= 1.0.0 [2008-12-06]
|
||||||
- Gemified!
|
- Gemified!
|
||||||
- Refactor of plugin into a Data Mapper style validator class which makes for a cleaner implementation and possible future Merb\Data Mapper support
|
- Refactor of plugin into a Data Mapper style validator class which makes for a cleaner implementation and possible future Merb\Data Mapper support
|
||||||
|
|||||||
23
README.rdoc
23
README.rdoc
@@ -1,7 +1,7 @@
|
|||||||
= validates_timeliness
|
= validates_timeliness
|
||||||
|
|
||||||
* Source: http://github.com/adzap/validates_timeliness
|
* Source: http://github.com/adzap/validates_timeliness
|
||||||
* Bugs: http://adzap.lighthouseapp.com/projects/14111-validates_timeliness
|
* Bugs: http://adzap.lighthouseapp.com/projects/14111-validates_timeliness
|
||||||
|
|
||||||
== DESCRIPTION:
|
== DESCRIPTION:
|
||||||
|
|
||||||
@@ -24,12 +24,16 @@ think should be a valid date or time string.
|
|||||||
|
|
||||||
* Respects new timezone features of Rails 2.1.
|
* Respects new timezone features of Rails 2.1.
|
||||||
|
|
||||||
|
* Supports Rails 2.2 I18n for the error messages
|
||||||
|
|
||||||
|
* Rspec matcher for testing model validation of dates and times
|
||||||
|
|
||||||
|
|
||||||
== INSTALLATION:
|
== INSTALLATION:
|
||||||
|
|
||||||
As plugin (from master)
|
As plugin (from master)
|
||||||
|
|
||||||
./script/plugin git://github.com/adzap/validates_timeliness
|
./script/plugin git://github.com/adzap/validates_timeliness.git
|
||||||
|
|
||||||
As gem
|
As gem
|
||||||
|
|
||||||
@@ -62,6 +66,7 @@ the valid range of dates or times allowed
|
|||||||
: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
|
||||||
:on_or_after - Attribute must be equal to or 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:
|
Regular validation options:
|
||||||
:allow_nil - Allow a nil value to be valid
|
:allow_nil - Allow a nil value to be valid
|
||||||
@@ -77,6 +82,7 @@ the valid range of dates or times allowed
|
|||||||
:on_or_before_message
|
:on_or_before_message
|
||||||
:after_message
|
:after_message
|
||||||
:on_or_after_message
|
:on_or_after_message
|
||||||
|
:between_message
|
||||||
|
|
||||||
The temporal restrictions can take 4 different value types:
|
The temporal restrictions can take 4 different value types:
|
||||||
|
|
||||||
@@ -84,6 +90,7 @@ The temporal restrictions can take 4 different value types:
|
|||||||
* Date, Time, or DateTime object value
|
* Date, Time, or DateTime object value
|
||||||
* Proc or lambda object
|
* Proc or lambda object
|
||||||
* A symbol matching the method name in the model
|
* 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
|
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
|
the same type as the validation method type. So using validates_date means all
|
||||||
@@ -193,7 +200,7 @@ of d/my/yy. By default the plugin uses the US formats as this is the Ruby defaul
|
|||||||
when it does date interpretation, and is in keeping PoLS (principle of least
|
when it does date interpretation, and is in keeping PoLS (principle of least
|
||||||
surprise).
|
surprise).
|
||||||
|
|
||||||
To switch to using the :after => 1.day.from_nowEuropean (or Rest of The World) formats put this in an
|
To switch to using the European (or Rest of The World) formats put this in an
|
||||||
initializer or environment.rb
|
initializer or environment.rb
|
||||||
|
|
||||||
ValidatesTimeliness::Formats.remove_us_formats
|
ValidatesTimeliness::Formats.remove_us_formats
|
||||||
@@ -264,7 +271,8 @@ For Rails 2.0/2.1:
|
|||||||
:before => "must be before %s",
|
:before => "must be before %s",
|
||||||
:on_or_before => "must be on or before %s",
|
:on_or_before => "must be on or before %s",
|
||||||
:after => "must be after %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.
|
Where %s is the interpolation value for the restriction.
|
||||||
@@ -275,8 +283,9 @@ Rails 2.2+ using the I18n system to define new defaults:
|
|||||||
activerecord:
|
activerecord:
|
||||||
errors:
|
errors:
|
||||||
messages:
|
messages:
|
||||||
on_or_before: "must equal to or before {{restriction}}"
|
on_or_before: "must be equal to or before {{restriction}}"
|
||||||
on_or_after: "must equal to or after {{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
|
The {{restriction}} signifies where the interpolation value for the restriction
|
||||||
will be inserted.
|
will be inserted.
|
||||||
|
|||||||
2
Rakefile
2
Rakefile
@@ -5,7 +5,7 @@ require 'date'
|
|||||||
require 'spec/rake/spectask'
|
require 'spec/rake/spectask'
|
||||||
|
|
||||||
GEM = "validates_timeliness"
|
GEM = "validates_timeliness"
|
||||||
GEM_VERSION = "1.0.0"
|
GEM_VERSION = "1.1.2"
|
||||||
AUTHOR = "Adam Meehan"
|
AUTHOR = "Adam Meehan"
|
||||||
EMAIL = "adam.meehan@gmail.com"
|
EMAIL = "adam.meehan@gmail.com"
|
||||||
HOMEPAGE = "http://github.com/adzap/validates_timeliness"
|
HOMEPAGE = "http://github.com/adzap/validates_timeliness"
|
||||||
|
|||||||
7
TODO
7
TODO
@@ -1,8 +1,5 @@
|
|||||||
- :between option
|
|
||||||
- :format option
|
- :format option
|
||||||
- :with_date and :with_time options
|
- :with_date and :with_time options
|
||||||
- Merb and Data Mapper support
|
|
||||||
- does it have before_type_cast
|
|
||||||
- timezone handling
|
|
||||||
- view helper support
|
|
||||||
- valid formats could come from locale file
|
- valid formats could come from locale file
|
||||||
|
- formats to use month and day names from i18n
|
||||||
|
- add replace_formats instead add_formats :before
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ module ValidatesTimeliness
|
|||||||
self.send("setup_for_rails_#{major}_#{minor}")
|
self.send("setup_for_rails_#{major}_#{minor}")
|
||||||
self.default_timezone = ::ActiveRecord::Base.default_timezone
|
self.default_timezone = ::ActiveRecord::Base.default_timezone
|
||||||
rescue
|
rescue
|
||||||
raise "Rails version #{Rails::VERSION::STRING} not yet supported by validates_timeliness plugin"
|
puts "Rails version #{Rails::VERSION::STRING} not explicitly supported by validates_timeliness plugin. You may encounter some problems."
|
||||||
|
resume
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -237,8 +237,7 @@ module ValidatesTimeliness
|
|||||||
|
|
||||||
return Regexp.new(regexp), format_proc(order)
|
return Regexp.new(regexp), format_proc(order)
|
||||||
rescue
|
rescue
|
||||||
puts "The following format regular expression failed to compile: #{regexp}\n from format #{string_format}."
|
raise "The following format regular expression failed to compile: #{regexp}\n from format #{string_format}."
|
||||||
raise
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Generates a proc which when executed maps the regexp capture groups to a
|
# Generates a proc which when executed maps the regexp capture groups to a
|
||||||
|
|||||||
@@ -9,3 +9,4 @@ en:
|
|||||||
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}}"
|
||||||
on_or_after: "must be on or after {{restriction}}"
|
on_or_after: "must be on or after {{restriction}}"
|
||||||
|
between: "must be between {{earliest}} and {{latest}}"
|
||||||
|
|||||||
@@ -2,120 +2,157 @@ module Spec
|
|||||||
module Rails
|
module Rails
|
||||||
module Matchers
|
module Matchers
|
||||||
class ValidateTimeliness
|
class ValidateTimeliness
|
||||||
cattr_accessor :test_values
|
|
||||||
|
|
||||||
@@test_values = {
|
VALIDITY_TEST_VALUES = {
|
||||||
:date => {:pass => '2000-01-01', :fail => '2000-01-32'},
|
:date => {:pass => '2000-01-01', :fail => '2000-01-32'},
|
||||||
:time => {:pass => '12:00', :fail => '25:00'},
|
:time => {:pass => '12:00', :fail => '25:00'},
|
||||||
:datetime => {:pass => '2000-01-01 00:00:00', :fail => '2000-01-32 00:00: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)
|
def initialize(attribute, options)
|
||||||
@expected, @options = attribute, options
|
@expected, @options = attribute, options
|
||||||
@validator = ValidatesTimeliness::Validator.new(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
|
end
|
||||||
|
|
||||||
def matches?(record)
|
def matches?(record)
|
||||||
@record = record
|
@record = record
|
||||||
type = options[:type]
|
@type = @options[:type]
|
||||||
|
|
||||||
invalid_value = @@test_values[type][:fail]
|
valid = test_validity
|
||||||
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_option(:before, :-) if options[:before] && valid
|
valid = test_option(:before) if @options[:before] && valid
|
||||||
valid = test_option(:after, :+) if options[:after] && 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_before) 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_after) if @options[:on_or_after] && valid
|
||||||
|
|
||||||
|
valid = test_between if @options[:between] && valid
|
||||||
|
|
||||||
return valid
|
return valid
|
||||||
end
|
end
|
||||||
|
|
||||||
def failure_message
|
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
|
end
|
||||||
|
|
||||||
def negative_failure_message
|
def negative_failure_message
|
||||||
"expected not to validate #{options[:type]} attribute #{expected.inspect}"
|
"expected not to validate #{@type} attribute #{@expected.inspect}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def description
|
def description
|
||||||
"have validated #{options[:type]} attribute #{expected.inspect}"
|
"have validated #{@type} attribute #{@expected.inspect}"
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
attr_reader :actual, :expected, :record, :options, :messages, :last_failure, :validator
|
|
||||||
|
|
||||||
def test_option(option, modifier, settings={})
|
def test_validity
|
||||||
settings.reverse_merge!(:modify_on => :valid)
|
invalid_value = VALIDITY_TEST_VALUES[@type][:fail]
|
||||||
boundary = parse_and_cast(options[option])
|
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
|
valid_value, invalid_value = if settings[:modify_on] == :valid
|
||||||
[ boundary.send(modifier, 1), boundary ]
|
[ boundary.send(method, 1), boundary ]
|
||||||
else
|
else
|
||||||
[ boundary, boundary.send(modifier, 1) ]
|
[ boundary, boundary.send(method, 1) ]
|
||||||
end
|
end
|
||||||
|
|
||||||
message = messages[option]
|
error_matching(invalid_value, option) &&
|
||||||
error_matching(invalid_value, /#{message}/) &&
|
no_error_matching(valid_value, option)
|
||||||
no_error_matching(valid_value, /#{message}/)
|
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
|
end
|
||||||
|
|
||||||
def parse_and_cast(value)
|
def parse_and_cast(value)
|
||||||
value = validator.send(:restriction_value, value, record)
|
value = @validator.send(:restriction_value, value, @record)
|
||||||
validator.send(:type_cast_value, value)
|
@validator.send(:type_cast_value, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
def error_matching(value, match)
|
def error_matching(value, option)
|
||||||
record.send("#{expected}=", value)
|
match = error_message_for(option)
|
||||||
record.valid?
|
@record.send("#{@expected}=", value)
|
||||||
errors = record.errors.on(expected)
|
@record.valid?
|
||||||
pass = [ errors ].flatten.any? {|error| match === error }
|
errors = @record.errors.on(@expected)
|
||||||
@last_failure = "error matching #{match.inspect} when value is #{format_value(value)}" unless pass
|
pass = [ errors ].flatten.any? {|error| /#{match}/ === error }
|
||||||
|
@last_failure = "error matching '#{match}' when value is #{format_value(value)}" unless pass
|
||||||
pass
|
pass
|
||||||
end
|
end
|
||||||
|
|
||||||
def no_error_matching(value, match)
|
def no_error_matching(value, option)
|
||||||
pass = !error_matching(value, match)
|
pass = !error_matching(value, option)
|
||||||
@last_failure = "no error matching #{match.inspect} when value is #{format_value(value)}" unless pass
|
unless pass
|
||||||
|
error = error_message_for(option)
|
||||||
|
@last_failure = "no error matching '#{error}' when value is #{format_value(value)}"
|
||||||
|
end
|
||||||
pass
|
pass
|
||||||
end
|
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 )
|
||||||
|
# get I18n message if defined and has interpolation keys in msg
|
||||||
|
if defined?(I18n) && !@validator.send(:custom_error_messages).include?(option)
|
||||||
|
msg = @record.errors.generate_message(@expected, option, interpolate)
|
||||||
|
else
|
||||||
|
msg = msg % interpolate
|
||||||
|
end
|
||||||
|
end
|
||||||
|
msg
|
||||||
|
end
|
||||||
|
|
||||||
def format_value(value)
|
def format_value(value)
|
||||||
return value if value.is_a?(String)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_date(attribute, options={})
|
def validate_date(attribute, options={})
|
||||||
options[:type] = :date
|
options[:type] = :date
|
||||||
validate_timeliness_of(attribute, options)
|
ValidateTimeliness.new(attribute, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_time(attribute, options={})
|
def validate_time(attribute, options={})
|
||||||
options[:type] = :time
|
options[:type] = :time
|
||||||
validate_timeliness_of(attribute, options)
|
ValidateTimeliness.new(attribute, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_datetime(attribute, options={})
|
def validate_datetime(attribute, options={})
|
||||||
options[:type] = :datetime
|
options[:type] = :datetime
|
||||||
validate_timeliness_of(attribute, options)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def validate_timeliness_of(attribute, options={})
|
|
||||||
ValidateTimeliness.new(attribute, options)
|
ValidateTimeliness.new(attribute, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -11,6 +11,14 @@ module ValidatesTimeliness
|
|||||||
:datetime => '%Y-%m-%d %H:%M:%S'
|
: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
|
attr_reader :configuration, :type
|
||||||
|
|
||||||
def initialize(configuration)
|
def initialize(configuration)
|
||||||
@@ -40,21 +48,17 @@ module ValidatesTimeliness
|
|||||||
end
|
end
|
||||||
|
|
||||||
def validate_restrictions(record, attr_name, value)
|
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)
|
value = type_cast_value(value)
|
||||||
|
|
||||||
restriction_methods.each do |option, method|
|
RESTRICTION_METHODS.each do |option, method|
|
||||||
next unless restriction = configuration[option]
|
next unless restriction = configuration[option]
|
||||||
begin
|
begin
|
||||||
compare = restriction_value(restriction, record)
|
restriction = restriction_value(restriction, record)
|
||||||
next if compare.nil?
|
next if restriction.nil?
|
||||||
compare = type_cast_value(compare)
|
restriction = type_cast_value(restriction)
|
||||||
|
|
||||||
unless value.send(method, compare)
|
unless evaluate_restriction(restriction, value, method)
|
||||||
add_error(record, attr_name, option, :restriction => compare.strftime(display))
|
add_error(record, attr_name, option, interpolation_values(option, restriction))
|
||||||
end
|
end
|
||||||
rescue
|
rescue
|
||||||
unless self.class.ignore_restriction_errors
|
unless self.class.ignore_restriction_errors
|
||||||
@@ -64,15 +68,41 @@ module ValidatesTimeliness
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_error(record, attr_name, message, interpolate={})
|
def interpolation_values(option, restriction)
|
||||||
if Rails::VERSION::STRING < '2.2'
|
format = self.class.error_value_formats[type]
|
||||||
message = error_messages[message] if message.is_a?(Symbol)
|
restriction = [restriction] unless restriction.is_a?(Array)
|
||||||
message = message % interpolate.values unless interpolate.empty?
|
|
||||||
record.errors.add(attr_name, message)
|
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
|
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=nil)
|
||||||
|
if defined?(I18n)
|
||||||
# use i18n support in AR for message or use custom message passed to validation method
|
# use i18n support in AR for message or use custom message passed to validation method
|
||||||
custom = custom_error_messages[message]
|
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
|
||||||
|
record.errors.add(attr_name, message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -83,7 +113,12 @@ module ValidatesTimeliness
|
|||||||
|
|
||||||
def custom_error_messages
|
def custom_error_messages
|
||||||
return @custom_error_messages if defined?(@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[1].to_sym] = v
|
||||||
|
end
|
||||||
|
msgs
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def restriction_value(restriction, record)
|
def restriction_value(restriction, record)
|
||||||
@@ -94,13 +129,20 @@ module ValidatesTimeliness
|
|||||||
restriction_value(record.send(restriction), record)
|
restriction_value(record.send(restriction), record)
|
||||||
when Proc
|
when Proc
|
||||||
restriction_value(restriction.call(record), record)
|
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
|
else
|
||||||
record.class.parse_date_time(restriction, type, false)
|
record.class.parse_date_time(restriction, type, false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def type_cast_value(value)
|
def type_cast_value(value)
|
||||||
case type
|
if value.is_a?(Array)
|
||||||
|
value.map {|v| type_cast_value(v) }
|
||||||
|
else
|
||||||
|
case type
|
||||||
when :time
|
when :time
|
||||||
value.to_dummy_time
|
value.to_dummy_time
|
||||||
when :date
|
when :date
|
||||||
@@ -109,10 +151,11 @@ module ValidatesTimeliness
|
|||||||
if value.is_a?(DateTime) || value.is_a?(Time)
|
if value.is_a?(DateTime) || value.is_a?(Time)
|
||||||
value.to_time
|
value.to_time
|
||||||
else
|
else
|
||||||
value.to_time(ValidatesTimelines.default_timezone)
|
value.to_time(ValidatesTimeliness.default_timezone)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
nil
|
nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -5,42 +5,59 @@ end
|
|||||||
|
|
||||||
class WithValidation < Person
|
class WithValidation < Person
|
||||||
validates_date :birth_date,
|
validates_date :birth_date,
|
||||||
:before => '2000-01-10', :after => '2000-01-01',
|
:before => '2000-01-10',
|
||||||
:on_or_before => '2000-01-09', :on_or_after => '2000-01-02'
|
:after => '2000-01-01',
|
||||||
|
:on_or_before => '2000-01-09',
|
||||||
|
:on_or_after => '2000-01-02',
|
||||||
|
:between => ['2000-01-01', '2000-01-03']
|
||||||
|
|
||||||
validates_time :birth_time,
|
validates_time :birth_time,
|
||||||
:before => '23:00', :after => '09:00',
|
:before => '23:00',
|
||||||
:on_or_before => '22:00', :on_or_after => '10:00'
|
:after => '09:00',
|
||||||
|
:on_or_before => '22:00',
|
||||||
|
:on_or_after => '10:00',
|
||||||
|
:between => ['09:00', '17:00']
|
||||||
|
|
||||||
validates_datetime :birth_date_and_time,
|
validates_datetime :birth_date_and_time,
|
||||||
:before => '2000-01-10 23:00', :after => '2000-01-01 09:00',
|
:before => '2000-01-10 23:00',
|
||||||
:on_or_before => '2000-01-09 23:00', :on_or_after => '2000-01-02 09:00'
|
:after => '2000-01-01 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
|
end
|
||||||
|
|
||||||
class CustomMessages < Person
|
class CustomMessages < Person
|
||||||
validates_date :birth_date, :invalid_date_message => 'is not really a date',
|
validates_date :birth_date,
|
||||||
:before => '2000-01-10', :before_message => 'is too late',
|
:invalid_date_message => 'is not really a date',
|
||||||
:after => '2000-01-01', :after_message => 'is too early',
|
:before => '2000-01-10',
|
||||||
:on_or_before=> '2000-01-09', :on_or_before_message => 'is just too late',
|
:before_message => 'is too late',
|
||||||
:on_or_after => '2000-01-02', :on_or_after_message => 'is just too early'
|
:after => '2000-01-01',
|
||||||
|
:after_message => 'is too early',
|
||||||
|
:on_or_before => '2000-01-09',
|
||||||
|
:on_or_before_message => 'is just too late',
|
||||||
|
:on_or_after => '2000-01-02',
|
||||||
|
:on_or_after_message => 'is just too early'
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "ValidateTimeliness matcher" do
|
describe "ValidateTimeliness matcher" do
|
||||||
attr_accessor :no_validation, :with_validation
|
attr_accessor :no_validation, :with_validation
|
||||||
|
|
||||||
|
@@attribute_for_type = { :date => :birth_date, :time => :birth_time, :datetime => :birth_date_and_time }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
@no_validation = NoValidation.new
|
@no_validation = NoValidation.new
|
||||||
@with_validation = WithValidation.new
|
@with_validation = WithValidation.new
|
||||||
end
|
end
|
||||||
|
|
||||||
[:date, :time, :datetime].each do |type|
|
[:date, :time, :datetime].each do |type|
|
||||||
attribute = type == :datetime ? :date_and_time : type
|
|
||||||
|
|
||||||
it "should report that #{type} is validated" do
|
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
|
end
|
||||||
|
|
||||||
it "should report that #{type} is not validated" do
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -52,18 +69,17 @@ describe "ValidateTimeliness matcher" do
|
|||||||
}
|
}
|
||||||
|
|
||||||
[:date, :time, :datetime].each do |type|
|
[:date, :time, :datetime].each do |type|
|
||||||
attribute = type == :datetime ? :date_and_time : type
|
|
||||||
|
|
||||||
it "should report that #{type} is validated" do
|
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
|
end
|
||||||
|
|
||||||
it "should report that #{type} is not validated when option value is incorrect" do
|
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
|
end
|
||||||
|
|
||||||
it "should report that #{type} is not validated with option" do
|
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
|
end
|
||||||
end
|
end
|
||||||
@@ -76,18 +92,17 @@ describe "ValidateTimeliness matcher" do
|
|||||||
}
|
}
|
||||||
|
|
||||||
[:date, :time, :datetime].each do |type|
|
[:date, :time, :datetime].each do |type|
|
||||||
attribute = type == :datetime ? :date_and_time : type
|
|
||||||
|
|
||||||
it "should report that #{type} is validated" do
|
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
|
end
|
||||||
|
|
||||||
it "should report that #{type} is not validated when option value is incorrect" do
|
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
|
end
|
||||||
|
|
||||||
it "should report that #{type} is not validated with option" do
|
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
|
end
|
||||||
end
|
end
|
||||||
@@ -100,18 +115,17 @@ describe "ValidateTimeliness matcher" do
|
|||||||
}
|
}
|
||||||
|
|
||||||
[:date, :time, :datetime].each do |type|
|
[:date, :time, :datetime].each do |type|
|
||||||
attribute = type == :datetime ? :date_and_time : type
|
|
||||||
|
|
||||||
it "should report that #{type} is validated" do
|
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
|
end
|
||||||
|
|
||||||
it "should report that #{type} is not validated when option value is incorrect" do
|
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
|
end
|
||||||
|
|
||||||
it "should report that #{type} is not validated with option" do
|
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
|
end
|
||||||
end
|
end
|
||||||
@@ -124,18 +138,40 @@ describe "ValidateTimeliness matcher" do
|
|||||||
}
|
}
|
||||||
|
|
||||||
[:date, :time, :datetime].each do |type|
|
[:date, :time, :datetime].each do |type|
|
||||||
attribute = type == :datetime ? :date_and_time : type
|
|
||||||
|
|
||||||
it "should report that #{type} is validated" do
|
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
|
end
|
||||||
|
|
||||||
it "should report that #{type} is not validated when option value is incorrect" do
|
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
|
end
|
||||||
|
|
||||||
it "should report that #{type} is not validated with option" do
|
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
|
end
|
||||||
end
|
end
|
||||||
@@ -175,4 +211,8 @@ describe "ValidateTimeliness matcher" do
|
|||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def attribute_for_type(type)
|
||||||
|
@@attribute_for_type[type.to_sym]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -43,6 +43,25 @@ describe ValidatesTimeliness::Validator do
|
|||||||
restriction_value(lambda {"2007-01-01 12:00"}, :datetime).should be_kind_of(Time)
|
restriction_value(lambda {"2007-01-01 12:00"}, :datetime).should be_kind_of(Time)
|
||||||
end
|
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)
|
def restriction_value(restriction, type)
|
||||||
configure_validator(:type => type)
|
configure_validator(:type => type)
|
||||||
validator.send(:restriction_value, restriction, person)
|
validator.send(:restriction_value, restriction, person)
|
||||||
@@ -212,83 +231,101 @@ describe ValidatesTimeliness::Validator do
|
|||||||
end
|
end
|
||||||
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
|
describe "for datetime type" do
|
||||||
before 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
|
end
|
||||||
|
|
||||||
it "should have error when value is past :on_or_before restriction" do
|
it "should have error when value is before earlist :between restriction" do
|
||||||
validate_with(:birth_date_and_time, Time.now.at_midnight + 1)
|
validate_with(:birth_date_and_time, 2.days.ago)
|
||||||
should_have_error(:birth_date_and_time, :on_of_before)
|
should_have_error(:birth_date_and_time, :between)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should be valid when value is equal to :on_or_before restriction" do
|
it "should have error when value is after latest :between restriction" do
|
||||||
validate_with(:birth_date_and_time, Time.now.at_midnight)
|
validate_with(:birth_date_and_time, 2.days.from_now)
|
||||||
should_have_no_error(:birth_date_and_time, :on_of_before)
|
should_have_error(:birth_date_and_time, :between)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should have error when value is before :on_or_after restriction" do
|
it "should be valid when value is equal to earliest :between restriction" do
|
||||||
validate_with(:birth_date_and_time, 1.days.ago - 1)
|
validate_with(:birth_date_and_time, 1.day.ago.at_midnight)
|
||||||
should_have_error(:birth_date_and_time, :on_of_after)
|
should_have_no_error(:birth_date_and_time, :between)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should be valid when value is value equal to :on_or_after restriction" do
|
it "should be valid when value is equal to latest :between restriction" do
|
||||||
validate_with(:birth_date_and_time, 1.day.ago)
|
validate_with(:birth_date_and_time, 1.day.from_now.at_midnight)
|
||||||
should_have_no_error(:birth_date_and_time, :on_of_after)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "for date type" do
|
describe "for date type" do
|
||||||
before :each do
|
before do
|
||||||
configure_validator(:on_or_before => 1.day.from_now, :on_or_after => 1.day.ago, :type => :date)
|
configure_validator(:type => :date, :between => [1.day.ago.to_date, 1.day.from_now.to_date])
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should have error when value is past :on_or_before restriction" do
|
it "should have error when value is before earlist :between restriction" do
|
||||||
validate_with(:birth_date, 2.days.from_now)
|
validate_with(:birth_date, 2.days.ago.to_date)
|
||||||
should_have_error(:birth_date, :on_or_before)
|
should_have_error(:birth_date, :between)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should have error when value is before :on_or_after restriction" do
|
it "should have error when value is after latest :between restriction" do
|
||||||
validate_with(:birth_date, 2.days.ago)
|
validate_with(:birth_date, 2.days.from_now.to_date)
|
||||||
should_have_error(:birth_date, :on_or_after)
|
should_have_error(:birth_date, :between)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should be valid when value is equal to :on_or_before restriction" do
|
it "should be valid when value is equal to earliest :between restriction" do
|
||||||
validate_with(:birth_date, 1.day.from_now)
|
validate_with(:birth_date, 1.day.ago.to_date)
|
||||||
should_have_no_error(:birth_date, :on_or_before)
|
should_have_no_error(:birth_date, :between)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should be valid when value value is equal to :on_or_after restriction" do
|
it "should be valid when value is equal to latest :between restriction" do
|
||||||
validate_with(:birth_date, 1.day.ago)
|
validate_with(:birth_date, 1.day.from_now.to_date)
|
||||||
should_have_no_error(:birth_date, :on_or_before)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "for time type" do
|
describe "for time type" do
|
||||||
before :each do
|
before do
|
||||||
configure_validator(:on_or_before => "23:00", :on_or_after => "06:00", :type => :time)
|
configure_validator(:type => :time, :between => ["09:00", "17:00"])
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should have error when value is past :on_or_before restriction" do
|
it "should have error when value is before earlist :between restriction" do
|
||||||
validate_with(:birth_time, "23:01")
|
validate_with(:birth_time, "08:59")
|
||||||
should_have_error(:birth_time, :on_or_before)
|
should_have_error(:birth_time, :between)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should have error when value is before :on_or_after restriction" do
|
it "should have error when value is after latest :between restriction" do
|
||||||
validate_with(:birth_time, "05:59")
|
validate_with(:birth_time, "17:01")
|
||||||
should_have_error(:birth_time, :on_or_after)
|
should_have_error(:birth_time, :between)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should be valid when value is on boundary of :on_or_before restriction" do
|
it "should be valid when value is equal to earliest :between restriction" do
|
||||||
validate_with(:birth_time, "23:00")
|
validate_with(:birth_time, "09:00")
|
||||||
should_have_no_error(:birth_time, :on_or_before)
|
should_have_no_error(:birth_time, :between)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should be valid when value is on boundary of :on_or_after restriction" do
|
it "should be valid when value is equal to latest :between restriction" do
|
||||||
validate_with(:birth_time, "06:00")
|
validate_with(:birth_time, "17:00")
|
||||||
should_have_no_error(:birth_time, :on_or_after)
|
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
|
end
|
||||||
end
|
end
|
||||||
@@ -326,6 +363,40 @@ describe ValidatesTimeliness::Validator do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "custom_error_messages" do
|
||||||
|
it "should return hash of custom error messages from configuration with _message truncated from keys" do
|
||||||
|
configure_validator(:type => :date, :invalid_date_message => 'thats no date')
|
||||||
|
validator.send(:custom_error_messages)[:invalid_date].should == 'thats no date'
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should return empty hash if no custom error messages in configuration" do
|
||||||
|
configure_validator(:type => :date)
|
||||||
|
validator.send(:custom_error_messages).should be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "interpolation_values" do
|
||||||
|
if defined?(I18n)
|
||||||
|
it "should return hash of interpolation keys with restriction values" do
|
||||||
|
before = '1900-01-01'
|
||||||
|
configure_validator(:type => :date, :before => before)
|
||||||
|
validator.send(:interpolation_values, :before, before.to_date).should == {:restriction => before}
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should return empty hash if no interpolation keys are in message" do
|
||||||
|
before = '1900-01-01'
|
||||||
|
configure_validator(:type => :date, :before => before, :before_message => 'too late')
|
||||||
|
validator.send(:interpolation_values, :before, before.to_date).should be_empty
|
||||||
|
end
|
||||||
|
else
|
||||||
|
it "should return array of interpolation values" do
|
||||||
|
before = '1900-01-01'
|
||||||
|
configure_validator(:type => :date, :before => before)
|
||||||
|
validator.send(:interpolation_values, :before, before.to_date).should == [before]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "restriction errors" do
|
describe "restriction errors" do
|
||||||
before :each do
|
before :each do
|
||||||
configure_validator(:type => :date, :before => lambda { raise })
|
configure_validator(:type => :date, :before => lambda { raise })
|
||||||
@@ -433,6 +504,6 @@ describe ValidatesTimeliness::Validator do
|
|||||||
def error_messages
|
def error_messages
|
||||||
return @error_messages if defined?(@error_messages)
|
return @error_messages if defined?(@error_messages)
|
||||||
messages = validator.send(: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
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
Gem::Specification.new do |s|
|
Gem::Specification.new do |s|
|
||||||
s.name = %q{validates_timeliness}
|
s.name = %q{validates_timeliness}
|
||||||
s.version = "1.0.0"
|
s.version = "1.1.2"
|
||||||
|
|
||||||
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||||
s.authors = ["Adam Meehan"]
|
s.authors = ["Adam Meehan"]
|
||||||
s.autorequire = %q{validates_timeliness}
|
s.autorequire = %q{validates_timeliness}
|
||||||
s.date = %q{2008-12-07}
|
s.date = %q{2009-01-12}
|
||||||
s.description = %q{Date and time validation plugin for Rails 2.x which allows custom formats}
|
s.description = %q{Date and time validation plugin for Rails 2.x which allows custom formats}
|
||||||
s.email = %q{adam.meehan@gmail.com}
|
s.email = %q{adam.meehan@gmail.com}
|
||||||
s.extra_rdoc_files = ["README.rdoc", "LICENSE", "TODO", "CHANGELOG"]
|
s.extra_rdoc_files = ["README.rdoc", "LICENSE", "TODO", "CHANGELOG"]
|
||||||
|
|||||||
Reference in New Issue
Block a user