mirror of
https://github.com/ditkrg/validates_timeliness.git
synced 2026-01-25 15:22:58 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76e159b350 | ||
|
|
c762b6d4f8 | ||
|
|
91f9f65bc0 | ||
|
|
6db8b7d908 | ||
|
|
d3c5101f92 | ||
|
|
899e96b880 | ||
|
|
162faf632a | ||
|
|
1b865cc834 | ||
|
|
c29478df45 | ||
|
|
df3283e5a1 | ||
|
|
0e382e15f2 | ||
|
|
9a697b9cab | ||
|
|
7bf7ed0569 | ||
|
|
a969a49ae8 | ||
|
|
687e61a3f2 | ||
|
|
4cc20ae620 | ||
|
|
2d510504e6 | ||
|
|
2028d68b17 | ||
|
|
e399c6b510 | ||
|
|
7aa1a87731 | ||
|
|
1a31e7463d |
@@ -1,3 +1,10 @@
|
|||||||
|
= 2.2.0 [2009-09-12]
|
||||||
|
- Ruby 1.9 support!
|
||||||
|
- Customise dummy date values for time types. See DUMMY DATE FOR TIME TYPES.
|
||||||
|
- Fixed matcher conflict with Shoulda. Load plugin matcher manually now see matcher section in README
|
||||||
|
- Fixed :ignore_usec when used with :with_time or :with_date
|
||||||
|
- Some clean up and refactoring
|
||||||
|
|
||||||
= 2.1.0 [2009-06-20]
|
= 2.1.0 [2009-06-20]
|
||||||
- Added ambiguous year threshold setting in Formats class to customize the threshold for 2 digit years (See README)
|
- Added ambiguous year threshold setting in Formats class to customize the threshold for 2 digit years (See README)
|
||||||
- Fixed interpolation values in custom error message for Rails 2.2+
|
- Fixed interpolation values in custom error message for Rails 2.2+
|
||||||
|
|||||||
30
README.rdoc
30
README.rdoc
@@ -22,9 +22,9 @@ think should be a valid date or time string.
|
|||||||
* Restores ability to see raw value entered for date/time attributes with
|
* Restores ability to see raw value entered for date/time attributes with
|
||||||
_before_type_cast modifier, which was lost in Rails 2.1.
|
_before_type_cast modifier, which was lost in Rails 2.1.
|
||||||
|
|
||||||
* Respects new timezone features of Rails 2.1.
|
* Supports Rails timezone handling
|
||||||
|
|
||||||
* Supports Rails 2.2 I18n for the error messages
|
* Supports Rails I18n for the error messages
|
||||||
|
|
||||||
* Rspec matcher for testing model validation of dates and times
|
* Rspec matcher for testing model validation of dates and times
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ temporal options.
|
|||||||
|
|
||||||
== EXAMPLES:
|
== EXAMPLES:
|
||||||
|
|
||||||
validates_date :date_of_birth :before => Proc.new { 18.years.ago },
|
validates_date :date_of_birth :before => lambda { 18.years.ago },
|
||||||
:before_message => "must be at least 18 years old"
|
:before_message => "must be at least 18 years old"
|
||||||
|
|
||||||
validates_time :breakfast_time, :on_or_after => '6:00am',
|
validates_time :breakfast_time, :on_or_after => '6:00am',
|
||||||
@@ -115,7 +115,7 @@ temporal options.
|
|||||||
:before => :second_breakfast_time,
|
:before => :second_breakfast_time,
|
||||||
:allow_nil => true
|
:allow_nil => true
|
||||||
|
|
||||||
validates_datetime :appointment_date, :before => Proc.new { 1.week.from_now }
|
validates_datetime :appointment_date, :before => lambda { 1.week.from_now }
|
||||||
|
|
||||||
validates_date :entry_date, :with_time => '17:00', :on_or_before => :competition_closing
|
validates_date :entry_date, :with_time => '17:00', :on_or_before => :competition_closing
|
||||||
|
|
||||||
@@ -263,6 +263,18 @@ Now you get:
|
|||||||
year of 20 is considered 1920
|
year of 20 is considered 1920
|
||||||
|
|
||||||
|
|
||||||
|
=== DUMMY DATE FOR TIME TYPES
|
||||||
|
|
||||||
|
Given that Ruby has no support for a time-only type, all time type columns are evaluated
|
||||||
|
as a regular Time class objects with a dummy date value set. Rails defines the dummy date as
|
||||||
|
2000-01-01. So a time of '12:30' is evaluated as a Time value of '2000-01-01 12:30'. If you
|
||||||
|
need to customize this for some reason you can do so as follows
|
||||||
|
|
||||||
|
ValidatesTimeliness::Formats.dummy_date_for_time_type = [2009, 1, 1]
|
||||||
|
|
||||||
|
The value should be an array of 3 values being year, month and day in that order.
|
||||||
|
|
||||||
|
|
||||||
=== TEMPORAL RESTRICTION ERRORS:
|
=== TEMPORAL RESTRICTION ERRORS:
|
||||||
|
|
||||||
When using the validation temporal restrictions there are times when the restriction
|
When using the validation temporal restrictions there are times when the restriction
|
||||||
@@ -355,9 +367,15 @@ To sweeten the deal that little bit more, you have an Rspec matcher available fo
|
|||||||
you model specs. Now you can easily test the validations you have just written
|
you model specs. Now you can easily test the validations you have just written
|
||||||
with the plugin or better yet *before* you write them! You just use the
|
with the plugin or better yet *before* you write them! You just use the
|
||||||
validation options you want as you would with the validation method. Those
|
validation options you want as you would with the validation method. Those
|
||||||
options are then verified and reported if they fail. Use it like so:
|
options are then verified and reported if they fail.
|
||||||
|
|
||||||
@person.should validate_date(:birth_date, :before => Time.now, :before_message => 'should be before today')
|
First require it in your spec_helper.rb
|
||||||
|
|
||||||
|
require 'validates_timeliness/matcher'
|
||||||
|
|
||||||
|
Use it like so:
|
||||||
|
|
||||||
|
@person.should validate_date(:birth_date, :before => Time.now, :before_message => 'should be before today')
|
||||||
|
|
||||||
|
|
||||||
The matcher names are just the singular of the validation methods.
|
The matcher names are just the singular of the validation methods.
|
||||||
|
|||||||
3
Rakefile
3
Rakefile
@@ -3,9 +3,10 @@ require 'rake/gempackagetask'
|
|||||||
require 'rubygems/specification'
|
require 'rubygems/specification'
|
||||||
require 'date'
|
require 'date'
|
||||||
require 'spec/rake/spectask'
|
require 'spec/rake/spectask'
|
||||||
|
require 'lib/validates_timeliness/version'
|
||||||
|
|
||||||
GEM = "validates_timeliness"
|
GEM = "validates_timeliness"
|
||||||
GEM_VERSION = "2.1.0"
|
GEM_VERSION = ValidatesTimeliness::VERSION
|
||||||
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"
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ require 'validates_timeliness/formats'
|
|||||||
require 'validates_timeliness/parser'
|
require 'validates_timeliness/parser'
|
||||||
require 'validates_timeliness/validator'
|
require 'validates_timeliness/validator'
|
||||||
require 'validates_timeliness/validation_methods'
|
require 'validates_timeliness/validation_methods'
|
||||||
require 'validates_timeliness/spec/rails/matchers/validate_timeliness' if ENV['RAILS_ENV'] == 'test'
|
|
||||||
|
|
||||||
require 'validates_timeliness/active_record/attribute_methods'
|
require 'validates_timeliness/active_record/attribute_methods'
|
||||||
require 'validates_timeliness/active_record/multiparameter_attributes'
|
require 'validates_timeliness/active_record/multiparameter_attributes'
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ module ValidatesTimeliness
|
|||||||
end
|
end
|
||||||
|
|
||||||
def read_attribute_before_type_cast_with_timeliness(attr_name)
|
def read_attribute_before_type_cast_with_timeliness(attr_name)
|
||||||
return @attributes_cache["_#{attr_name}_before_type_cast"] if @attributes_cache.has_key?("_#{attr_name}_before_type_cast")
|
cached_attr = "_#{attr_name}_before_type_cast"
|
||||||
|
return @attributes_cache[cached_attr] if @attributes_cache.has_key?(cached_attr)
|
||||||
read_attribute_before_type_cast_without_timeliness(attr_name)
|
read_attribute_before_type_cast_without_timeliness(attr_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -50,11 +51,9 @@ module ValidatesTimeliness
|
|||||||
if [:date, :time, :datetime].include?(column.type)
|
if [:date, :time, :datetime].include?(column.type)
|
||||||
time_zone_aware = create_time_zone_conversion_attribute?(name, column) rescue false
|
time_zone_aware = create_time_zone_conversion_attribute?(name, column) rescue false
|
||||||
|
|
||||||
class_eval <<-EOV
|
define_method("#{name}=") do |value|
|
||||||
def #{name}=(value)
|
write_date_time_attribute(name, value, column.type, time_zone_aware)
|
||||||
write_date_time_attribute('#{name}', value, #{column.type.inspect}, #{time_zone_aware})
|
end
|
||||||
end
|
|
||||||
EOV
|
|
||||||
timeliness_methods << name
|
timeliness_methods << name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,6 +5,33 @@ module ValidatesTimeliness
|
|||||||
end
|
end
|
||||||
|
|
||||||
module ActiveRecord
|
module ActiveRecord
|
||||||
|
|
||||||
|
class << self
|
||||||
|
|
||||||
|
def time_array_to_string(values, type)
|
||||||
|
values.collect! {|v| v.to_s }
|
||||||
|
|
||||||
|
case type
|
||||||
|
when :date
|
||||||
|
extract_date_from_multiparameter_attributes(values)
|
||||||
|
when :time
|
||||||
|
extract_time_from_multiparameter_attributes(values)
|
||||||
|
when :datetime
|
||||||
|
extract_date_from_multiparameter_attributes(values) + " " + extract_time_from_multiparameter_attributes(values)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def extract_date_from_multiparameter_attributes(values)
|
||||||
|
year = ValidatesTimeliness::Formats.unambiguous_year(values[0].rjust(2, "0"))
|
||||||
|
[year, *values.slice(1, 2).map { |s| s.rjust(2, "0") }].join("-")
|
||||||
|
end
|
||||||
|
|
||||||
|
def extract_time_from_multiparameter_attributes(values)
|
||||||
|
values[3..5].map { |s| s.rjust(2, "0") }.join(":")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
module MultiparameterAttributes
|
module MultiparameterAttributes
|
||||||
|
|
||||||
def self.included(base)
|
def self.included(base)
|
||||||
@@ -23,7 +50,7 @@ module ValidatesTimeliness
|
|||||||
if values.empty?
|
if values.empty?
|
||||||
send("#{name}=", nil)
|
send("#{name}=", nil)
|
||||||
else
|
else
|
||||||
value = time_array_to_string(values, column.type)
|
value = ValidatesTimeliness::ActiveRecord.time_array_to_string(values, column.type)
|
||||||
send("#{name}=", value)
|
send("#{name}=", value)
|
||||||
end
|
end
|
||||||
rescue => ex
|
rescue => ex
|
||||||
@@ -37,28 +64,6 @@ module ValidatesTimeliness
|
|||||||
execute_callstack_for_multiparameter_attributes_without_timeliness(callstack)
|
execute_callstack_for_multiparameter_attributes_without_timeliness(callstack)
|
||||||
end
|
end
|
||||||
|
|
||||||
def time_array_to_string(values, type)
|
|
||||||
values.collect! {|v| v.to_s }
|
|
||||||
|
|
||||||
case type
|
|
||||||
when :date
|
|
||||||
extract_date_from_multiparameter_attributes(values)
|
|
||||||
when :time
|
|
||||||
extract_time_from_multiparameter_attributes(values)
|
|
||||||
when :datetime
|
|
||||||
extract_date_from_multiparameter_attributes(values) + " " + extract_time_from_multiparameter_attributes(values)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def extract_date_from_multiparameter_attributes(values)
|
|
||||||
year = ValidatesTimeliness::Formats.unambiguous_year(values[0].rjust(2, "0"))
|
|
||||||
[year, *values.slice(1, 2).map { |s| s.rjust(2, "0") }].join("-")
|
|
||||||
end
|
|
||||||
|
|
||||||
def extract_time_from_multiparameter_attributes(values)
|
|
||||||
values[3..5].map { |s| s.rjust(2, "0") }.join(":")
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ module ValidatesTimeliness
|
|||||||
|
|
||||||
|
|
||||||
# Set the threshold value for a two digit year to be considered last century
|
# Set the threshold value for a two digit year to be considered last century
|
||||||
|
#
|
||||||
# Default: 30
|
# Default: 30
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
@@ -32,6 +33,14 @@ module ValidatesTimeliness
|
|||||||
cattr_accessor :ambiguous_year_threshold
|
cattr_accessor :ambiguous_year_threshold
|
||||||
self.ambiguous_year_threshold = 30
|
self.ambiguous_year_threshold = 30
|
||||||
|
|
||||||
|
# Set the dummy date part for a time type value. Should be an array of 3 values
|
||||||
|
# being year, month and day in that order.
|
||||||
|
#
|
||||||
|
# Default: [ 2000, 1, 1 ] same as ActiveRecord
|
||||||
|
#
|
||||||
|
cattr_accessor :dummy_date_for_time_type
|
||||||
|
self.dummy_date_for_time_type = [ 2000, 1, 1 ]
|
||||||
|
|
||||||
# Format tokens:
|
# Format tokens:
|
||||||
# y = year
|
# y = year
|
||||||
# m = month
|
# m = month
|
||||||
@@ -179,6 +188,7 @@ module ValidatesTimeliness
|
|||||||
options.reverse_merge!(:strict => true)
|
options.reverse_merge!(:strict => true)
|
||||||
|
|
||||||
sets = if options[:format]
|
sets = if options[:format]
|
||||||
|
options[:strict] = true
|
||||||
[ send("#{type}_expressions").assoc(options[:format]) ]
|
[ send("#{type}_expressions").assoc(options[:format]) ]
|
||||||
else
|
else
|
||||||
expression_set(type, string)
|
expression_set(type, string)
|
||||||
@@ -195,7 +205,11 @@ module ValidatesTimeliness
|
|||||||
break(proc) if matches = full.match(string.strip)
|
break(proc) if matches = full.match(string.strip)
|
||||||
end
|
end
|
||||||
last = options[:include_offset] ? 8 : 7
|
last = options[:include_offset] ? 8 : 7
|
||||||
processor.call(*matches[1..last]) if matches
|
if matches
|
||||||
|
values = processor.call(*matches[1..last])
|
||||||
|
values[0..2] = dummy_date_for_time_type if type == :time
|
||||||
|
return values
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Delete formats of specified type. Error raised if format not found.
|
# Delete formats of specified type. Error raised if format not found.
|
||||||
|
|||||||
1
lib/validates_timeliness/matcher.rb
Normal file
1
lib/validates_timeliness/matcher.rb
Normal file
@@ -0,0 +1 @@
|
|||||||
|
require 'validates_timeliness/spec/rails/matchers/validate_timeliness'
|
||||||
@@ -7,28 +7,24 @@ module ValidatesTimeliness
|
|||||||
return nil if raw_value.blank?
|
return nil if raw_value.blank?
|
||||||
return raw_value if raw_value.acts_like?(:time) || raw_value.is_a?(Date)
|
return raw_value if raw_value.acts_like?(:time) || raw_value.is_a?(Date)
|
||||||
|
|
||||||
options.reverse_merge!(:strict => true)
|
time_array = ValidatesTimeliness::Formats.parse(raw_value, type, options.reverse_merge(:strict => true))
|
||||||
|
return nil if time_array.nil?
|
||||||
time_array = ValidatesTimeliness::Formats.parse(raw_value, type, options)
|
|
||||||
raise if time_array.nil?
|
|
||||||
|
|
||||||
# Rails dummy time date part is defined as 2000-01-01
|
if type == :date
|
||||||
time_array[0..2] = 2000, 1, 1 if type == :time
|
Date.new(*time_array[0..2]) rescue nil
|
||||||
|
else
|
||||||
# Date.new enforces days per month, unlike Time
|
make_time(time_array[0..7])
|
||||||
date = Date.new(*time_array[0..2]) unless type == :time
|
end
|
||||||
|
|
||||||
return date if type == :date
|
|
||||||
|
|
||||||
make_time(time_array[0..7])
|
|
||||||
rescue
|
|
||||||
nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def make_time(time_array)
|
def make_time(time_array)
|
||||||
|
# Enforce date part validity which Time class does not
|
||||||
|
return nil unless Date.valid_civil?(*time_array[0..2])
|
||||||
|
|
||||||
if Time.respond_to?(:zone) && ValidatesTimeliness.use_time_zones
|
if Time.respond_to?(:zone) && ValidatesTimeliness.use_time_zones
|
||||||
Time.zone.local(*time_array)
|
Time.zone.local(*time_array)
|
||||||
else
|
else
|
||||||
|
# Older AR way of handling times with datetime fallback
|
||||||
begin
|
begin
|
||||||
time_zone = ValidatesTimeliness.default_timezone
|
time_zone = ValidatesTimeliness.default_timezone
|
||||||
Time.send(time_zone, *time_array)
|
Time.send(time_zone, *time_array)
|
||||||
@@ -38,6 +34,8 @@ module ValidatesTimeliness
|
|||||||
DateTime.civil(*(time_array << zone_offset))
|
DateTime.civil(*(time_array << zone_offset))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
rescue ArgumentError, TypeError
|
||||||
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -28,13 +28,12 @@ module Spec
|
|||||||
|
|
||||||
valid = test_validity
|
valid = test_validity
|
||||||
|
|
||||||
valid = test_option(:equal_to) if @options[:equal_to] && valid
|
valid = test_option(:equal_to) if valid && @options[:equal_to]
|
||||||
valid = test_option(:before) if @options[:before] && valid
|
valid = test_option(:before) if valid && @options[:before]
|
||||||
valid = test_option(:after) if @options[:after] && valid
|
valid = test_option(:after) if valid && @options[:after]
|
||||||
valid = test_option(:on_or_before) if @options[:on_or_before] && valid
|
valid = test_option(:on_or_before) if valid && @options[:on_or_before]
|
||||||
valid = test_option(:on_or_after) if @options[:on_or_after] && valid
|
valid = test_option(:on_or_after) if valid && @options[:on_or_after]
|
||||||
|
valid = test_between if valid && @options[:between]
|
||||||
valid = test_between if @options[:between] && valid
|
|
||||||
|
|
||||||
return valid
|
return valid
|
||||||
end
|
end
|
||||||
@@ -124,9 +123,14 @@ module Spec
|
|||||||
restriction = [restriction] unless restriction.is_a?(Array)
|
restriction = [restriction] unless restriction.is_a?(Array)
|
||||||
restriction.map! {|r| @validator.class.send(:type_cast_value, r, @type) }
|
restriction.map! {|r| @validator.class.send(:type_cast_value, r, @type) }
|
||||||
interpolate = @validator.send(:interpolation_values, option, restriction )
|
interpolate = @validator.send(:interpolation_values, option, restriction )
|
||||||
|
|
||||||
# get I18n message if defined and has interpolation keys in msg
|
# get I18n message if defined and has interpolation keys in msg
|
||||||
if defined?(I18n) && !@validator.send(:custom_error_messages).include?(option)
|
if defined?(I18n) && !@validator.send(:custom_error_messages).include?(option)
|
||||||
msg = @record.errors.generate_message(@expected, option, interpolate)
|
msg = if defined?(ActiveRecord::Error)
|
||||||
|
ActiveRecord::Error.new(@record, @expected, option, interpolate).message
|
||||||
|
else
|
||||||
|
@record.errors.generate_message(@expected, option, interpolate)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
msg = msg % interpolate
|
msg = msg % interpolate
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -32,21 +32,13 @@ module ValidatesTimeliness
|
|||||||
raw_value = raw_value(record, attr_name) || value
|
raw_value = raw_value(record, attr_name) || value
|
||||||
|
|
||||||
if value.is_a?(String) || configuration[:format]
|
if value.is_a?(String) || configuration[:format]
|
||||||
strict = !configuration[:format].nil?
|
value = ValidatesTimeliness::Parser.parse(raw_value, type, :strict => false, :format => configuration[:format])
|
||||||
value = ValidatesTimeliness::Parser.parse(raw_value, type, :strict => strict, :format => configuration[:format])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return if (raw_value.nil? && configuration[:allow_nil]) || (raw_value.blank? && configuration[:allow_blank])
|
return if (raw_value.nil? && configuration[:allow_nil]) || (raw_value.blank? && configuration[:allow_blank])
|
||||||
|
|
||||||
if raw_value.blank?
|
return add_error(record, attr_name, :blank) if raw_value.blank?
|
||||||
add_error(record, attr_name, :blank)
|
return add_error(record, attr_name, "invalid_#{type}".to_sym) if value.nil?
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if value.nil?
|
|
||||||
add_error(record, attr_name, "invalid_#{type}".to_sym)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
validate_restrictions(record, attr_name, value)
|
validate_restrictions(record, attr_name, value)
|
||||||
end
|
end
|
||||||
@@ -62,21 +54,20 @@ module ValidatesTimeliness
|
|||||||
end
|
end
|
||||||
|
|
||||||
def validate_restrictions(record, attr_name, value)
|
def validate_restrictions(record, attr_name, value)
|
||||||
value = if configuration[:with_time] || configuration[:with_date]
|
if configuration[:with_time] || configuration[:with_date]
|
||||||
restriction_type = :datetime
|
value = combine_date_and_time(value, record)
|
||||||
combine_date_and_time(value, record)
|
|
||||||
else
|
|
||||||
restriction_type = type
|
|
||||||
self.class.type_cast_value(value, type, configuration[:ignore_usec])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
value = self.class.type_cast_value(value, implied_type, configuration[:ignore_usec])
|
||||||
|
|
||||||
return if value.nil?
|
return if value.nil?
|
||||||
|
|
||||||
RESTRICTION_METHODS.each do |option, method|
|
RESTRICTION_METHODS.each do |option, method|
|
||||||
next unless restriction = configuration[option]
|
next unless restriction = configuration[option]
|
||||||
begin
|
begin
|
||||||
restriction = self.class.evaluate_option_value(restriction, restriction_type, record)
|
restriction = self.class.evaluate_option_value(restriction, implied_type, record)
|
||||||
next if restriction.nil?
|
next if restriction.nil?
|
||||||
restriction = self.class.type_cast_value(restriction, restriction_type, configuration[:ignore_usec])
|
restriction = self.class.type_cast_value(restriction, implied_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))
|
||||||
@@ -155,6 +146,10 @@ module ValidatesTimeliness
|
|||||||
options.assert_valid_keys(VALID_OPTIONS - invalid_for_type)
|
options.assert_valid_keys(VALID_OPTIONS - invalid_for_type)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def implied_type
|
||||||
|
@implied_type ||= configuration[:with_date] || configuration[:with_time] ? :datetime : type
|
||||||
|
end
|
||||||
|
|
||||||
# class methods
|
# class methods
|
||||||
class << self
|
class << self
|
||||||
|
|
||||||
@@ -185,7 +180,8 @@ module ValidatesTimeliness
|
|||||||
when Symbol
|
when Symbol
|
||||||
evaluate_option_value(record.send(value), type, record)
|
evaluate_option_value(record.send(value), type, record)
|
||||||
when Proc
|
when Proc
|
||||||
evaluate_option_value(value.call(record), type, record)
|
result = value.arity > 0 ? value.call(record) : value.call
|
||||||
|
evaluate_option_value(result, type, record)
|
||||||
when Array
|
when Array
|
||||||
value.map {|r| evaluate_option_value(r, type, record) }.sort
|
value.map {|r| evaluate_option_value(r, type, record) }.sort
|
||||||
when Range
|
when Range
|
||||||
|
|||||||
3
lib/validates_timeliness/version.rb
Normal file
3
lib/validates_timeliness/version.rb
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module ValidatesTimeliness
|
||||||
|
VERSION = "2.2.0"
|
||||||
|
end
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
||||||
|
|
||||||
describe ValidatesTimeliness::ActionView::InstanceTag, :type => :helper do
|
ValidatesTimeliness.enable_datetime_select_extension!
|
||||||
|
|
||||||
|
describe 'ValidatesTimeliness::ActionView::InstanceTag' do
|
||||||
|
include ActionView::Helpers::DateHelper
|
||||||
|
include ActionController::Assertions::SelectorAssertions
|
||||||
|
|
||||||
before do
|
before do
|
||||||
@person = Person.new
|
@person = Person.new
|
||||||
|
|||||||
@@ -6,17 +6,17 @@ describe ValidatesTimeliness::ActiveRecord::MultiparameterAttributes do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "should convert array for datetime type into datetime string" do
|
it "should convert array for datetime type into datetime string" do
|
||||||
time_string = obj.time_array_to_string([2000,2,1,9,10,11], :datetime)
|
time_string = time_array_to_string([2000,2,1,9,10,11], :datetime)
|
||||||
time_string.should == "2000-02-01 09:10:11"
|
time_string.should == "2000-02-01 09:10:11"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should convert array for date type into date string" do
|
it "should convert array for date type into date string" do
|
||||||
time_string = obj.time_array_to_string([2000,2,1], :date)
|
time_string = time_array_to_string([2000,2,1], :date)
|
||||||
time_string.should == "2000-02-01"
|
time_string.should == "2000-02-01"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should convert array for time type into time string" do
|
it "should convert array for time type into time string" do
|
||||||
time_string = obj.time_array_to_string([2000,1,1,9,10,11], :time)
|
time_string = time_array_to_string([2000,1,1,9,10,11], :time)
|
||||||
time_string.should == "09:10:11"
|
time_string.should == "09:10:11"
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -44,5 +44,9 @@ describe ValidatesTimeliness::ActiveRecord::MultiparameterAttributes do
|
|||||||
obj.send(:execute_callstack_for_multiparameter_attributes, @callstack)
|
obj.send(:execute_callstack_for_multiparameter_attributes, @callstack)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def time_array_to_string(*args)
|
||||||
|
ValidatesTimeliness::ActiveRecord.time_array_to_string(*args)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
||||||
|
|
||||||
describe ValidatesTimeliness::Formats do
|
describe ValidatesTimeliness::Formats do
|
||||||
attr_reader :formats
|
|
||||||
|
|
||||||
before do
|
|
||||||
@formats = ValidatesTimeliness::Formats
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "format proc generator" do
|
describe "format proc generator" do
|
||||||
it "should generate proc which outputs date array with values in correct order" do
|
it "should generate proc which outputs date array with values in correct order" do
|
||||||
@@ -104,7 +99,7 @@ describe ValidatesTimeliness::Formats do
|
|||||||
|
|
||||||
it "should return time array from date string" do
|
it "should return time array from date string" do
|
||||||
time_array = formats.parse('12:13:14', :time, :strict => true)
|
time_array = formats.parse('12:13:14', :time, :strict => true)
|
||||||
time_array.should == [0,0,0,12,13,14,0]
|
time_array.should == [2000,1,1,12,13,14,0]
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should return date array from time string" do
|
it "should return date array from time string" do
|
||||||
@@ -134,7 +129,7 @@ describe ValidatesTimeliness::Formats do
|
|||||||
|
|
||||||
it "should ignore date when extracting time and strict is false" do
|
it "should ignore date when extracting time and strict is false" do
|
||||||
time_array = formats.parse('2000-02-01 12:13', :time, :strict => false)
|
time_array = formats.parse('2000-02-01 12:13', :time, :strict => false)
|
||||||
time_array.should == [0,0,0,12,13,0,0]
|
time_array.should == [2000,1,1,12,13,0,0]
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should return zone offset when :include_offset options is true" do
|
it "should return zone offset when :include_offset options is true" do
|
||||||
@@ -177,6 +172,22 @@ describe ValidatesTimeliness::Formats do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "parse with custom dummy date values" do
|
||||||
|
before(:all) do
|
||||||
|
@old_dummy_date = formats.dummy_date_for_time_type
|
||||||
|
formats.dummy_date_for_time_type = [2009,1,1]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should return time array with custom dummy date" do
|
||||||
|
time_array = formats.parse('12:13:14', :time, :strict => true)
|
||||||
|
time_array.should == [2009,1,1,12,13,14,0]
|
||||||
|
end
|
||||||
|
|
||||||
|
after(:all) do
|
||||||
|
formats.dummy_date_for_time_type = @old_dummy_date
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "removing formats" do
|
describe "removing formats" do
|
||||||
it "should remove format from format array" do
|
it "should remove format from format array" do
|
||||||
formats.remove_formats(:time, 'h.nn_ampm')
|
formats.remove_formats(:time, 'h.nn_ampm')
|
||||||
@@ -219,7 +230,7 @@ describe ValidatesTimeliness::Formats do
|
|||||||
formats.add_formats(:time, "ss:hh:nn", :before => 'hh:nn:ss')
|
formats.add_formats(:time, "ss:hh:nn", :before => 'hh:nn:ss')
|
||||||
validate("59:23:58", :time).should be_true
|
validate("59:23:58", :time).should be_true
|
||||||
time_array = formats.parse('59:23:58', :time)
|
time_array = formats.parse('59:23:58', :time)
|
||||||
time_array.should == [0,0,0,23,58,59,0]
|
time_array.should == [2000,1,1,23,58,59,0]
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should raise error if format exists" do
|
it "should raise error if format exists" do
|
||||||
@@ -251,6 +262,11 @@ describe ValidatesTimeliness::Formats do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def formats
|
||||||
|
ValidatesTimeliness::Formats
|
||||||
|
end
|
||||||
|
|
||||||
def validate(time_string, type)
|
def validate(time_string, type)
|
||||||
valid = false
|
valid = false
|
||||||
formats.send("#{type}_expressions").each do |format, regexp, processor|
|
formats.send("#{type}_expressions").each do |format, regexp, processor|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# ginger spec
|
# ginger spec
|
||||||
#
|
#
|
||||||
Ginger.configure do |config|
|
Ginger.configure do |config|
|
||||||
rails_versions = ['2.0.2', '2.1.2', '2.2.2', '2.3.2']
|
rails_versions = ['2.0.2', '2.1.2', '2.2.2', '2.3.3', '2.3.4']
|
||||||
|
|
||||||
rails_versions.each do |v|
|
rails_versions.each do |v|
|
||||||
g = Ginger::Scenario.new("Rails #{v}")
|
g = Ginger::Scenario.new("Rails #{v}")
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
||||||
|
require 'validates_timeliness/matcher'
|
||||||
|
|
||||||
class NoValidation < Person
|
class NoValidation < Person
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -45,8 +45,7 @@ if RAILS_VER >= '2.1'
|
|||||||
end
|
end
|
||||||
|
|
||||||
require 'validates_timeliness'
|
require 'validates_timeliness'
|
||||||
|
require 'validates_timeliness/matcher'
|
||||||
ValidatesTimeliness.enable_datetime_select_extension!
|
|
||||||
|
|
||||||
ActiveRecord::Migration.verbose = false
|
ActiveRecord::Migration.verbose = false
|
||||||
ActiveRecord::Base.establish_connection({:adapter => 'sqlite3', :database => ':memory:'})
|
ActiveRecord::Base.establish_connection({:adapter => 'sqlite3', :database => ':memory:'})
|
||||||
|
|||||||
@@ -358,18 +358,6 @@ describe ValidatesTimeliness::Validator do
|
|||||||
should_have_error(:birth_date_and_time, :equal_to)
|
should_have_error(:birth_date_and_time, :equal_to)
|
||||||
end
|
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
|
it "should be valid when value is equal to :equal_to restriction" do
|
||||||
validate_with(:birth_date_and_time, Time.now)
|
validate_with(:birth_date_and_time, Time.now)
|
||||||
should_have_no_error(:birth_date_and_time, :equal_to)
|
should_have_no_error(:birth_date_and_time, :equal_to)
|
||||||
@@ -409,6 +397,16 @@ describe ValidatesTimeliness::Validator do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "instance with :ignore_usec option" do
|
||||||
|
|
||||||
|
it "should ignore usec on time values when evaluated" 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
|
||||||
|
|
||||||
|
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
|
||||||
@@ -423,20 +421,31 @@ describe ValidatesTimeliness::Validator do
|
|||||||
should_have_no_error(:birth_date, :on_or_before)
|
should_have_no_error(:birth_date, :on_or_before)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "should should ignore usec value on combined value if :ignore_usec option is true" do
|
||||||
|
configure_validator(:type => :date, :with_time => Time.mktime(2000,1,1,12,30,0,500), :equal_to => Time.mktime(2000,1,1,12,30), :ignore_usec => true)
|
||||||
|
validate_with(:birth_date, "2000-01-01")
|
||||||
|
should_have_no_error(:birth_date, :equal_to)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "instance with :with_date option" do
|
describe "instance with :with_date option" do
|
||||||
|
|
||||||
it "should validate time attribute as datetime combining value of :with_date against restrictions " do
|
it "should validate time attribute as datetime combining value of :with_date against restrictions " do
|
||||||
configure_validator(:type => :time, :with_date => '2009-01-01', :on_or_before => Time.mktime(2000,1,1,12,30))
|
configure_validator(:type => :time, :with_date => '2009-01-01', :on_or_before => Time.mktime(2000,1,1,12,30))
|
||||||
validate_with(:birth_date, "12:30")
|
validate_with(:birth_time, "12:30")
|
||||||
should_have_error(:birth_date, :on_or_before)
|
should_have_error(:birth_time, :on_or_before)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should skip restriction validation if :with_date value is nil" do
|
it "should skip restriction validation if :with_date value is nil" do
|
||||||
configure_validator(:type => :time, :with_date => nil, :on_or_before => Time.mktime(2000,1,1,12,30))
|
configure_validator(:type => :time, :with_date => nil, :on_or_before => Time.mktime(2000,1,1,12,30))
|
||||||
validate_with(:birth_date, "12:30")
|
validate_with(:birth_time, "12:30")
|
||||||
should_have_no_error(:birth_date, :on_or_before)
|
should_have_no_error(:birth_time, :on_or_before)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should should ignore usec value on combined value if :ignore_usec option is true" do
|
||||||
|
configure_validator(:type => :time, :with_date => Date.new(2000,1,1), :on_or_before => Time.mktime(2000,1,1,12,30), :ignore_usec => true)
|
||||||
|
validate_with(:birth_time, Time.mktime(2000,1,1,12,30,0,50))
|
||||||
|
should_have_no_error(:birth_time, :on_or_before)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -2,16 +2,16 @@
|
|||||||
|
|
||||||
Gem::Specification.new do |s|
|
Gem::Specification.new do |s|
|
||||||
s.name = %q{validates_timeliness}
|
s.name = %q{validates_timeliness}
|
||||||
s.version = "2.1.0"
|
s.version = "2.2.0"
|
||||||
|
|
||||||
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{2009-06-20}
|
s.date = %q{2009-09-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"]
|
||||||
s.files = ["LICENSE", "README.rdoc", "Rakefile", "TODO", "CHANGELOG", "lib/validates_timeliness", "lib/validates_timeliness/active_record", "lib/validates_timeliness/active_record/multiparameter_attributes.rb", "lib/validates_timeliness/active_record/attribute_methods.rb", "lib/validates_timeliness/parser.rb", "lib/validates_timeliness/core_ext", "lib/validates_timeliness/core_ext/date.rb", "lib/validates_timeliness/core_ext/time.rb", "lib/validates_timeliness/core_ext/date_time.rb", "lib/validates_timeliness/validator.rb", "lib/validates_timeliness/validation_methods.rb", "lib/validates_timeliness/locale", "lib/validates_timeliness/locale/en.yml", "lib/validates_timeliness/spec", "lib/validates_timeliness/spec/rails", "lib/validates_timeliness/spec/rails/matchers", "lib/validates_timeliness/spec/rails/matchers/validate_timeliness.rb", "lib/validates_timeliness/action_view", "lib/validates_timeliness/action_view/instance_tag.rb", "lib/validates_timeliness/formats.rb", "lib/validates_timeliness.rb", "spec/active_record", "spec/active_record/multiparameter_attributes_spec.rb", "spec/active_record/attribute_methods_spec.rb", "spec/formats_spec.rb", "spec/parser_spec.rb", "spec/core_ext", "spec/core_ext/dummy_time_spec.rb", "spec/spec_helper.rb", "spec/ginger_scenarios.rb", "spec/time_travel", "spec/time_travel/time_extensions.rb", "spec/time_travel/time_travel.rb", "spec/time_travel/MIT-LICENSE", "spec/spec", "spec/spec/rails", "spec/spec/rails/matchers", "spec/spec/rails/matchers/validate_timeliness_spec.rb", "spec/validator_spec.rb", "spec/action_view", "spec/action_view/instance_tag_spec.rb", "spec/resources", "spec/resources/schema.rb", "spec/resources/application.rb", "spec/resources/person.rb", "spec/resources/sqlite_patch.rb"]
|
s.files = ["LICENSE", "README.rdoc", "Rakefile", "TODO", "CHANGELOG", "lib/validates_timeliness", "lib/validates_timeliness/active_record", "lib/validates_timeliness/active_record/multiparameter_attributes.rb", "lib/validates_timeliness/active_record/attribute_methods.rb", "lib/validates_timeliness/parser.rb", "lib/validates_timeliness/version.rb", "lib/validates_timeliness/core_ext", "lib/validates_timeliness/core_ext/date.rb", "lib/validates_timeliness/core_ext/time.rb", "lib/validates_timeliness/core_ext/date_time.rb", "lib/validates_timeliness/validator.rb", "lib/validates_timeliness/validation_methods.rb", "lib/validates_timeliness/locale", "lib/validates_timeliness/locale/en.yml", "lib/validates_timeliness/spec", "lib/validates_timeliness/spec/rails", "lib/validates_timeliness/spec/rails/matchers", "lib/validates_timeliness/spec/rails/matchers/validate_timeliness.rb", "lib/validates_timeliness/matcher.rb", "lib/validates_timeliness/action_view", "lib/validates_timeliness/action_view/instance_tag.rb", "lib/validates_timeliness/formats.rb", "lib/validates_timeliness.rb", "spec/active_record", "spec/active_record/multiparameter_attributes_spec.rb", "spec/active_record/attribute_methods_spec.rb", "spec/formats_spec.rb", "spec/parser_spec.rb", "spec/core_ext", "spec/core_ext/dummy_time_spec.rb", "spec/spec_helper.rb", "spec/ginger_scenarios.rb", "spec/time_travel", "spec/time_travel/time_extensions.rb", "spec/time_travel/time_travel.rb", "spec/time_travel/MIT-LICENSE", "spec/spec", "spec/spec/rails", "spec/spec/rails/matchers", "spec/spec/rails/matchers/validate_timeliness_spec.rb", "spec/validator_spec.rb", "spec/action_view", "spec/action_view/instance_tag_spec.rb", "spec/resources", "spec/resources/schema.rb", "spec/resources/application.rb", "spec/resources/person.rb", "spec/resources/sqlite_patch.rb"]
|
||||||
s.homepage = %q{http://github.com/adzap/validates_timeliness}
|
s.homepage = %q{http://github.com/adzap/validates_timeliness}
|
||||||
s.require_paths = ["lib"]
|
s.require_paths = ["lib"]
|
||||||
s.rubyforge_project = %q{validatestime}
|
s.rubyforge_project = %q{validatestime}
|
||||||
|
|||||||
Reference in New Issue
Block a user