Compare commits

...

35 Commits

Author SHA1 Message Date
Adam Meehan
7886132114 version 3.0.5 2011-05-09 17:34:09 +10:00
Adam Meehan
c3b1ddffbb Readme typo 2011-05-09 07:45:38 +10:00
Adam Meehan
ac98978441 Better timeliness_type_cast_code 2011-05-09 07:43:41 +10:00
Adam Meehan
ea7c9ec7be Type caste to Date for date columns in AR after parsing string in attribute writer 2011-04-27 07:37:26 +10:00
Adam Meehan
e3dea5aebd use activemodel scoped class name in helper method to remove need for .kind override 2011-02-24 21:12:49 +11:00
Adam Meehan
9d654b1122 update to rails 3.0.4 2011-02-24 07:59:01 +11:00
Adam Meehan
2822e368e3 Exit restriction validation on first restriction error 2011-02-24 07:58:48 +11:00
Adam Meehan
2244d5e74d Use bundle gem tasks and move gemspec from Rakefile the .gemspec 2011-02-24 07:44:39 +11:00
Adam Meehan
1c70af4dba simplify data select spec 2011-02-23 20:05:09 +11:00
Adam Meehan
dac62060df version 3.0.5 2011-01-29 17:42:42 +11:00
Adam Meehan
4efa91f3b0 some Rakefile cleanup and simplification 2011-01-29 17:39:00 +11:00
Adam Meehan
38457ec334 change spec config setup to use class method with_config 2011-01-29 16:33:37 +11:00
Adam Meehan
3793ef2ed4 fix for validation nil value with :format option plugin parser disabled (issue 34) 2011-01-29 16:07:56 +11:00
Adam Meehan
983e80f239 move some files into spec/support and include ModelHelpers in config 2011-01-28 19:36:02 +11:00
Adam Meehan
bbb752e4e3 version 3.0.4 2011-01-22 11:16:10 +11:00
Adam Meehan
9d4ac8d513 update test gems 2011-01-22 11:15:15 +11:00
Adam Meehan
54347ee682 doc tweak 2011-01-22 10:49:59 +11:00
Adam Meehan
54ba4a038c use namespaced validator class name for the :timeliness option 2011-01-22 10:48:40 +11:00
Adam Meehan
7b5b11ad63 use class_attribute again, now that I know how to use it safely 2011-01-22 10:47:22 +11:00
Edgars Beigarts
d14ae09820 Fixed :between option. 2011-01-21 11:02:59 +02:00
Adam Meehan
01d1dc7c5e version 3.0.3 2010-12-11 09:17:31 +11:00
Adam Meehan
b09f937688 tiny consistency change 2010-12-11 09:17:08 +11:00
Adam Meehan
509336e080 Fix type_cast_value for values which don't respond to to_time or to_date (renatoelias) 2010-12-11 09:13:35 +11:00
Adam Meehan
e345b5dc7d update README with supported Ruby platforms 2010-12-04 17:14:46 +11:00
Adam Meehan
57eef70b7c remove ruby-debug from Gemfile for now 2010-12-04 17:14:16 +11:00
Adam Meehan
46eafe31a1 version 3.0.2 2010-12-04 16:40:13 +11:00
Adam Meehan
f17a799b5c updated Timeliness to 0.3.2 for zone and offset in string support 2010-12-04 16:34:34 +11:00
Adam Meehan
3bf364a395 reluctantly overriding whole execute_callstack_for_multiparameter_attributes method
this fixes issue for Date column types. Damn method is just too
unwieldly and should be refactored in Rails.
2010-12-04 16:29:05 +11:00
Adam Meehan
bfcab52c22 can use super for some InstanceTag methods
cleans up for DateTimeSelect extension a little
2010-11-02 10:13:13 +11:00
Adam Meehan
20c0aaa793 version 3.0.1 2010-11-02 09:53:25 +11:00
Adam Meehan
a756b66f75 add contributors link and change credits to maintainers 2010-11-02 09:51:45 +11:00
José Valim
889b5a9b07 Move timeliness defined methods to a module so they can be overwritten. 2010-11-01 14:56:03 -02:00
José Valim
0e3f56e26d Update Gemfile.
* Use gemspec to retrieve timeliness and other gem specifications.
* Remove test group (since it is the only option) and break groups into AR and Mongoid.
2010-11-01 14:47:19 -02:00
Adam Meehan
7ca662ada8 readme words 2010-10-21 08:25:35 +11:00
Adam Meehan
03effb9e52 readme tweaks 2010-10-21 07:50:37 +11:00
31 changed files with 516 additions and 419 deletions

View File

@@ -1,3 +1,25 @@
= 3.0.6 [2011-05-09]
* Fix for AR type conversion for date columns when using plugin parser.
* Add timeliness_type_cast_code for ORM specific type casting after parsing.
= 3.0.5 [2011-01-29]
* Fix for Conversion#parse when given nil value (closes issue #34)
= 3.0.4 [2011-01-22]
* Fix :between option which was being ignored (ebeigarts)
* Use class_attribute to remove deprecated class_inheritable_accessor
* Namespace copied validator class to ActiveModel::Validations::Timeliness for :timeliness option
= 3.0.3 [2010-12-11]
* Fix validation of values which don't respond to to_date or to_time (renatoelias)
= 3.0.2 [2010-12-04]
* Fix AR multiparameter extension for Date columns
* Update to Timeliness 0.3.2 for zone abbreviation and offset support
= 3.0.1 [2010-11-02]
* Generate timeliness write methods in an included module to allow overriding in model class (josevalim)
= 3.0.0 [2010-10-18]
* Rails 3 and ActiveModel compatibility
* Uses ActiveModel::EachValidator as validator base class.

26
Gemfile
View File

@@ -1,16 +1,18 @@
source 'http://rubygems.org'
gem 'timeliness', '~> 0.1.1'
gemspec
group :test do
gem 'ZenTest'
gem 'rails', '3.0.0'
gem 'sqlite3-ruby', :require => 'sqlite3'
gem 'mongoid', '2.0.0.beta.17'
gem 'bson_ext', '1.0.4'
gem 'rspec', '>= 2.0.0.beta.17'
gem 'rspec-rails', '>= 2.0.0.beta.17'
gem 'timecop'
gem 'rspec_tag_matchers'
gem 'ruby-debug'
gem 'ZenTest'
gem 'rails', '3.0.7'
gem 'rspec', '~> 2.4'
gem 'rspec-rails', '~> 2.4'
gem 'timecop'
gem 'rspec_tag_matchers'
group :mongoid do
gem 'mongoid', '2.0.0.rc.8'
end
group :active_record do
gem 'sqlite3-ruby', :require => 'sqlite3'
end

View File

@@ -1,106 +1,106 @@
PATH
remote: .
specs:
validates_timeliness (3.0.6)
timeliness (~> 0.3.3)
GEM
remote: http://rubygems.org/
specs:
ZenTest (4.4.0)
ZenTest (4.5.0)
abstract (1.0.0)
actionmailer (3.0.0)
actionpack (= 3.0.0)
mail (~> 2.2.5)
actionpack (3.0.0)
activemodel (= 3.0.0)
activesupport (= 3.0.0)
actionmailer (3.0.7)
actionpack (= 3.0.7)
mail (~> 2.2.15)
actionpack (3.0.7)
activemodel (= 3.0.7)
activesupport (= 3.0.7)
builder (~> 2.1.2)
erubis (~> 2.6.6)
i18n (~> 0.4.1)
i18n (~> 0.5.0)
rack (~> 1.2.1)
rack-mount (~> 0.6.12)
rack-test (~> 0.5.4)
rack-mount (~> 0.6.14)
rack-test (~> 0.5.7)
tzinfo (~> 0.3.23)
activemodel (3.0.0)
activesupport (= 3.0.0)
activemodel (3.0.7)
activesupport (= 3.0.7)
builder (~> 2.1.2)
i18n (~> 0.4.1)
activerecord (3.0.0)
activemodel (= 3.0.0)
activesupport (= 3.0.0)
arel (~> 1.0.0)
i18n (~> 0.5.0)
activerecord (3.0.7)
activemodel (= 3.0.7)
activesupport (= 3.0.7)
arel (~> 2.0.2)
tzinfo (~> 0.3.23)
activeresource (3.0.0)
activemodel (= 3.0.0)
activesupport (= 3.0.0)
activesupport (3.0.0)
arel (1.0.1)
activesupport (~> 3.0.0)
bson (1.0.4)
bson_ext (1.0.4)
activeresource (3.0.7)
activemodel (= 3.0.7)
activesupport (= 3.0.7)
activesupport (3.0.7)
arel (2.0.9)
bson (1.3.0)
builder (2.1.2)
columnize (0.3.1)
diff-lcs (1.1.2)
erubis (2.6.6)
abstract (>= 1.0.0)
i18n (0.4.1)
linecache (0.43)
mail (2.2.6.1)
i18n (0.5.0)
mail (2.2.19)
activesupport (>= 2.3.6)
mime-types
treetop (>= 1.4.5)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
mime-types (1.16)
mongo (1.0.7)
bson (>= 1.0.4)
mongoid (2.0.0.beta.17)
activemodel (~> 3.0.0)
bson (= 1.0.4)
mongo (= 1.0.7)
mongo (1.3.0)
bson (>= 1.3.0)
mongoid (2.0.0.rc.8)
activemodel (~> 3.0)
mongo (~> 1.2)
tzinfo (~> 0.3.22)
will_paginate (~> 3.0.pre)
nokogiri (1.4.3.1)
nokogiri (1.4.4)
polyglot (0.3.1)
rack (1.2.1)
rack-mount (0.6.13)
rack (1.2.2)
rack-mount (0.6.14)
rack (>= 1.0.0)
rack-test (0.5.4)
rack-test (0.5.7)
rack (>= 1.0)
rails (3.0.0)
actionmailer (= 3.0.0)
actionpack (= 3.0.0)
activerecord (= 3.0.0)
activeresource (= 3.0.0)
activesupport (= 3.0.0)
bundler (~> 1.0.0)
railties (= 3.0.0)
railties (3.0.0)
actionpack (= 3.0.0)
activesupport (= 3.0.0)
rake (>= 0.8.4)
thor (~> 0.14.0)
rails (3.0.7)
actionmailer (= 3.0.7)
actionpack (= 3.0.7)
activerecord (= 3.0.7)
activeresource (= 3.0.7)
activesupport (= 3.0.7)
bundler (~> 1.0)
railties (= 3.0.7)
railties (3.0.7)
actionpack (= 3.0.7)
activesupport (= 3.0.7)
rake (>= 0.8.7)
thor (~> 0.14.4)
rake (0.8.7)
rspec (2.0.0.beta.22)
rspec-core (= 2.0.0.beta.22)
rspec-expectations (= 2.0.0.beta.22)
rspec-mocks (= 2.0.0.beta.22)
rspec-core (2.0.0.beta.22)
rspec-expectations (2.0.0.beta.22)
diff-lcs (>= 1.1.2)
rspec-mocks (2.0.0.beta.22)
rspec-core (= 2.0.0.beta.22)
rspec-expectations (= 2.0.0.beta.22)
rspec-rails (2.0.0.beta.22)
rspec (= 2.0.0.beta.22)
rspec (2.5.0)
rspec-core (~> 2.5.0)
rspec-expectations (~> 2.5.0)
rspec-mocks (~> 2.5.0)
rspec-core (2.5.1)
rspec-expectations (2.5.0)
diff-lcs (~> 1.1.2)
rspec-mocks (2.5.0)
rspec-rails (2.5.0)
actionpack (~> 3.0)
activesupport (~> 3.0)
railties (~> 3.0)
rspec (~> 2.5.0)
rspec_tag_matchers (1.0.0)
nokogiri (>= 1.4.0)
rspec-rails (>= 1.2.6)
ruby-debug (0.10.3)
columnize (>= 0.1)
ruby-debug-base (~> 0.10.3.0)
ruby-debug-base (0.10.3)
linecache (>= 0.3)
sqlite3-ruby (1.3.1)
thor (0.14.1)
sqlite3 (1.3.3)
sqlite3-ruby (1.3.3)
sqlite3 (>= 1.3.3)
thor (0.14.6)
timecop (0.3.5)
timeliness (0.1.1)
treetop (1.4.8)
timeliness (0.3.3)
treetop (1.4.9)
polyglot (>= 0.3.1)
tzinfo (0.3.23)
tzinfo (0.3.27)
will_paginate (3.0.pre2)
PLATFORMS
@@ -108,13 +108,11 @@ PLATFORMS
DEPENDENCIES
ZenTest
bson_ext (= 1.0.4)
mongoid (= 2.0.0.beta.17)
rails (= 3.0.0)
rspec (>= 2.0.0.beta.17)
rspec-rails (>= 2.0.0.beta.17)
mongoid (= 2.0.0.rc.8)
rails (= 3.0.7)
rspec (~> 2.4)
rspec-rails (~> 2.4)
rspec_tag_matchers
ruby-debug
sqlite3-ruby
timecop
timeliness (~> 0.1.1)
validates_timeliness!

View File

@@ -18,12 +18,13 @@ If you a looking for the old version for Rails 2.x go here[http://github.com/adz
* Only Rails date/time validation plugin offering complete validation (See ORM/ODM support)
* Adds extensions to fix Rails date/time select issues
* Adds extensions to fix Rails date/time select issues (See Extensions)
* Uses extensible date/time parser ({timeliness gem}[http://github.com/adzap/timeliness])
* Uses extensible date/time parser (Using {timeliness gem}[http://github.com/adzap/timeliness]. See Plugin Parser)
* Supports I18n for the error messages
* Supports Ruby 1.8.x, 1.9.x and Rubinius.
== Installation
@@ -31,10 +32,10 @@ As plugin (from master)
rails plugin install git://github.com/adzap/validates_timeliness.git
As gem (in beta)
As gem
# in Gemfile
gem 'validates_timeliness', '~> 3.0.0'
gem 'validates_timeliness', '~> 3.0.2'
# Run bundler
$ bundle install
@@ -46,12 +47,14 @@ Then run
This creates configuration initializer and locale files. In the initializer, you there are a number of config
options to customize the plugin.
NOTE: You may wish to enable the plugin parser and the extensions to start. Please read those sections first.
== Examples
validates_datetime :occurred_at
validates_date :date_of_birth :before => lambda { 18.years.ago },
validates_date :date_of_birth, :before => lambda { 18.years.ago },
:before_message => "must be at least 18 years old"
validates_datetime :finish_time, :after => :start_time # Method symbol
@@ -175,7 +178,8 @@ You can also use validation options for custom error messages. The following opt
:after_message
:on_or_after_message
Note: There is no :between_message option. The between error message should be defined using the :on_or_before and :on_or_after messages.
Note: There is no :between_message option. The between error message should be defined using the
:on_or_before and :on_or_after messages.
It is highly recommended you use the I18n system for error messages.
@@ -254,36 +258,42 @@ To turn them on/off:
config.ignore_restriction_errors = true
=== Display Invalid Values in Select Helpers
The plugin offers an extension for ActionView to allowing invalid
date and time values to be redisplayed to the user as feedback, instead of
a blank field which happens by default in Rails. Though the date helpers make this a
pretty rare occurrence, given the select dropdowns for each date/time component, but
it may be something of interest.
To activate it, put this in an initializer:
# in the setup block
config.enable_date_time_select_extension!
== Extensions
=== Strict Parsing for Select Helpers
When using date/time select helpers, the component values are handled by ActiveRecord using
the Time class to instantiate them into a time value. But this mean that some invalid dates,
the Time class to instantiate them into a time value. This means that some invalid dates,
such as 31st June, are shifted forward and treated as valid. To handle these cases in a strict
way you can enable the plugin handler to treat them as invalid dates.
way, you can enable the plugin extension to treat them as invalid dates.
To activate it, put this in an initializer:
To activate it, uncomment this line in the initializer:
# in the setup block
config.enable_multiparameter_extension!
== Credits
=== Display Invalid Values in Select Helpers
* Adam Meehan (adam.meehan@gmail.com, http://github.com/adzap)
The plugin offers an extension for ActionView to allowing invalid date and time values to be
redisplayed to the user as feedback, instead of a blank field which happens by default in
Rails. Though the date helpers make this a pretty rare occurrence, given the select dropdowns
for each date/time component, but it may be something of interest.
To activate it, uncomment this line in the initializer:
# in the setup block
config.enable_date_time_select_extension!
== Contributors
To see the generous people who have contributed code, take a look at the {contributors list}[http://github.com/adzap/validates_timeliness/contributors].
== Maintainers
* {Adam Meehan}[http://github.com/adzap]
== License

View File

@@ -1,37 +1,11 @@
require 'rubygems'
require 'bundler'
Bundler::GemHelper.install_tasks
require 'rake/rdoctask'
require 'rake/gempackagetask'
require 'rubygems/specification'
require 'rspec/core/rake_task'
require 'lib/validates_timeliness/version'
GEM_NAME = "validates_timeliness"
GEM_VERSION = ValidatesTimeliness::VERSION
spec = Gem::Specification.new do |s|
s.name = GEM_NAME
s.version = GEM_VERSION
s.platform = Gem::Platform::RUBY
s.rubyforge_project = "validates_timeliness"
s.has_rdoc = true
s.extra_rdoc_files = ["README.rdoc", "CHANGELOG.rdoc", "LICENSE"]
s.summary = %q{Date and time validation plugin for Rails which allows custom formats}
s.description = s.summary
s.author = "Adam Meehan"
s.email = "adam.meehan@gmail.com"
s.homepage = "http://github.com/adzap/validates_timeliness"
s.require_path = 'lib'
s.files = %w(validates_timeliness.gemspec LICENSE CHANGELOG.rdoc README.rdoc Rakefile) + Dir.glob("{lib,spec}/**/*")
s.add_runtime_dependency 'timeliness', '~> 0.1.0'
end
desc 'Default: run specs.'
task :default => :spec
desc "Run specs"
RSpec::Core::RakeTask.new do |t|
t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
end
RSpec::Core::RakeTask.new(:spec)
desc "Generate code coverage"
RSpec::Core::RakeTask.new(:coverage) do |t|
@@ -48,18 +22,5 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
rdoc.rdoc_files.include('lib/**/*.rb')
end
Rake::GemPackageTask.new(spec) do |pkg|
pkg.gem_spec = spec
end
desc "Install the gem locally"
task :install => [:package] do
sh %{gem install pkg/#{GEM_NAME}-#{GEM_VERSION}}
end
desc "Create a gemspec file"
task :make_spec do
File.open("#{GEM_NAME}.gemspec", "w") do |file|
file.puts spec.to_ruby
end
end
desc 'Default: run specs.'
task :default => :spec

View File

@@ -3,7 +3,7 @@ module ValidatesTimeliness
extend ActiveSupport::Concern
included do
class_inheritable_accessor :timeliness_validated_attributes
class_attribute :timeliness_validated_attributes
self.timeliness_validated_attributes = []
end
@@ -31,18 +31,16 @@ module ValidatesTimeliness
end
def define_timeliness_write_method(attr_name)
type = timeliness_attribute_type(attr_name)
timezone_aware = timeliness_attribute_timezone_aware?(attr_name)
method_body, line = <<-EOV, __LINE__ + 1
def #{attr_name}=(value)
@timeliness_cache ||= {}
@timeliness_cache["#{attr_name}"] = value
#{ "value = Timeliness::Parser.parse(value, :#{type}, :zone => (:current if #{timezone_aware})) if value.is_a?(String)" if ValidatesTimeliness.use_plugin_parser }
#{ "if value.is_a?(String)\n#{timeliness_type_cast_code(attr_name, 'value')}\nend" if ValidatesTimeliness.use_plugin_parser }
super
end
EOV
class_eval(method_body, __FILE__, line)
generated_timeliness_methods.module_eval(method_body, __FILE__, line)
end
def define_timeliness_before_type_cast_method(attr_name)
@@ -51,7 +49,19 @@ module ValidatesTimeliness
_timeliness_raw_value_for('#{attr_name}')
end
EOV
class_eval(method_body, __FILE__, line)
generated_timeliness_methods.module_eval(method_body, __FILE__, line)
end
def timeliness_type_cast_code(attr_name, var_name)
type = timeliness_attribute_type(attr_name)
timezone_aware = timeliness_attribute_timezone_aware?(attr_name)
timezone = :current if timezone_aware
"#{var_name} = Timeliness::Parser.parse(#{var_name}, :#{type}, :zone => #{timezone.inspect})"
end
def generated_timeliness_methods
@generated_timeliness_methods ||= Module.new.tap { |m| include(m) }
end
end

View File

@@ -2,7 +2,7 @@ module ValidatesTimeliness
module Conversion
def type_cast_value(value, type)
return nil if value.nil?
return nil if value.nil? || !value.respond_to?(:to_time)
value = value.in_time_zone if value.acts_like?(:time) && @timezone_aware
value = case type
@@ -56,6 +56,7 @@ module ValidatesTimeliness
end
def parse(value)
return nil if value.nil?
if ValidatesTimeliness.use_plugin_parser
Timeliness::Parser.parse(value, @type, :zone => (:current if @timezone_aware), :format => options[:format], :strict => false)
else

View File

@@ -10,7 +10,6 @@ module ValidatesTimeliness
included do
alias_method_chain :datetime_selector, :timeliness
alias_method_chain :value, :timeliness
end
module InstanceMethods
@@ -22,13 +21,13 @@ module ValidatesTimeliness
datetime_selector_without_timeliness(*args)
end
def value_with_timeliness(object)
def value(object)
unless @timeliness_date_or_time_tag && @template_object.params[@object_name]
return value_without_timeliness(object)
return super
end
pairs = @template_object.params[@object_name].select {|k,v| k =~ /^#{@method_name}\(/ }
return value_without_timeliness(object) if pairs.empty?
return super if pairs.empty?
values = [nil] * 6
pairs.map do |(param, value)|

View File

@@ -3,26 +3,64 @@ module ValidatesTimeliness
module MultiparameterHandler
extend ActiveSupport::Concern
# Stricter handling of date and time values from multiparameter
# assignment from the date/time select view helpers
included do
alias_method_chain :instantiate_time_object, :timeliness
alias_method_chain :execute_callstack_for_multiparameter_attributes, :timeliness
end
private
# Stricter handling of date and time values from multiparameter
# assignment from the date/time select view helpers
#
def instantiate_time_object_with_timeliness(name, values)
unless Date.valid_civil?(*values[0..2])
value = [values[0], *values[1..2].map {|s| s.to_s.rjust(2,"0")} ].join("-")
value += ' ' + values[3..5].map {|s| s.to_s.rjust(2, "0") }.join(":") unless values[3..5].empty?
return value
end
def invalid_multiparameter_date_or_time_as_string(values)
value = [values[0], *values[1..2].map {|s| s.to_s.rjust(2,"0")} ].join("-")
value += ' ' + values[3..5].map {|s| s.to_s.rjust(2, "0") }.join(":") unless values[3..5].empty?
value
end
if self.class.send(:create_time_zone_conversion_attribute?, name, column_for_attribute(name))
Time.zone.local(*values)
def instantiate_time_object_with_timeliness(name, values)
if Date.valid_civil?(*values[0..2])
instantiate_time_object_without_timeliness(name, values)
else
Time.time_with_datetime_fallback(self.class.default_timezone, *values)
invalid_multiparameter_date_or_time_as_string(values)
end
end
def instantiate_date_object(name, values)
values = values.map { |v| v.nil? ? 1 : v }
Date.new(*values)
rescue ArgumentError => ex
invalid_multiparameter_date_or_time_as_string(values)
end
def execute_callstack_for_multiparameter_attributes_with_timeliness(callstack)
errors = []
callstack.each do |name, values_with_empty_parameters|
begin
klass = (self.class.reflect_on_aggregation(name.to_sym) || column_for_attribute(name)).klass
values = values_with_empty_parameters.reject { |v| v.nil? }
if values.empty?
send(name + "=", nil)
else
value = if Time == klass
instantiate_time_object(name, values)
elsif Date == klass
instantiate_date_object(name, values_with_empty_parameters)
else
klass.new(*values)
end
send(name + "=", value)
end
rescue => ex
errors << ActiveRecord::AttributeAssignmentError.new("error on assignment #{values.inspect} to #{name}", ex, name)
end
end
unless errors.empty?
raise ActiveRecord::MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes"
end
end

View File

@@ -20,7 +20,7 @@ module ActiveModel
self.timeliness_validated_attributes ||= []
self.timeliness_validated_attributes += (attr_names - self.timeliness_validated_attributes)
end
validates_with ValidatesTimeliness::Validator, options
validates_with TimelinessValidator, options
end
end

View File

@@ -18,6 +18,15 @@ module ValidatesTimeliness
def timeliness_attribute_type(attr_name)
columns_hash[attr_name.to_s].type
end
def timeliness_type_cast_code(attr_name, var_name)
type = timeliness_attribute_type(attr_name)
<<-END
#{super}
#{var_name} = #{var_name}.to_date if #{var_name} && :#{type} == :date
END
end
end
module InstanceMethods

View File

@@ -16,17 +16,10 @@ module ValidatesTimeliness
attr_names.each { |attr_name| define_timeliness_write_method(attr_name) }
end
def define_timeliness_write_method(attr_name)
def timeliness_type_cast_code(attr_name, var_name)
type = timeliness_attribute_type(attr_name)
method_body, line = <<-EOV, __LINE__ + 1
def #{attr_name}=(value)
@timeliness_cache ||= {}
@timeliness_cache["#{attr_name}"] = value
#{ "value = Timeliness::Parser.parse(value, :#{type}) if value.is_a?(String)" if ValidatesTimeliness.use_plugin_parser }
write_attribute(:#{attr_name}, value)
end
EOV
class_eval(method_body, __FILE__, line)
"#{var_name} = Timeliness::Parser.parse(value, :#{type})"
end
def timeliness_attribute_type(attr_name)

View File

@@ -20,19 +20,18 @@ module ValidatesTimeliness
:datetime => '%Y-%m-%d %H:%M:%S'
}.freeze
def self.kind
:timeliness
end
RESTRICTION_ERROR_MESSAGE = "Error occurred validating %s for %s restriction:\n%s"
def initialize(options)
@type = options.delete(:type) || :datetime
@allow_nil, @allow_blank = options.delete(:allow_nil), options.delete(:allow_blank)
@restrictions_to_check = RESTRICTIONS.keys & options.keys
if range = options.delete(:between)
raise ArgumentError, ":between must be a Range or an Array" unless range.is_a?(Range) || range.is_a?(Array)
options[:on_or_after], options[:on_or_before] = range.first, range.last
end
@restrictions_to_check = RESTRICTIONS.keys & options.keys
super
end
@@ -44,17 +43,22 @@ module ValidatesTimeliness
value = parse(raw_value) if value.is_a?(String) || options[:format]
value = type_cast_value(value, @type)
return add_error(record, attr_name, :"invalid_#{@type}") if value.blank?
add_error(record, attr_name, :"invalid_#{@type}") and return if value.blank?
validate_restrictions(record, attr_name, value)
end
def validate_restrictions(record, attr_name, value)
@restrictions_to_check.each do |restriction|
begin
restriction_value = type_cast_value(evaluate_option_value(options[restriction], record), @type)
unless value.send(RESTRICTIONS[restriction], restriction_value)
return add_error(record, attr_name, restriction, restriction_value)
add_error(record, attr_name, restriction, restriction_value) and break
end
rescue => e
unless ValidatesTimeliness.ignore_restriction_errors
add_error(record, attr_name, "Error occurred validating #{attr_name} for #{restriction.inspect} restriction:\n#{e.message}")
message = RESTRICTION_ERROR_MESSAGE % [ attr_name, restriction.inspect, e.message ]
add_error(record, attr_name, message) and break
end
end
end
@@ -72,9 +76,8 @@ module ValidatesTimeliness
end
def attribute_raw_value(record, attr_name)
if record.respond_to?(:_timeliness_raw_value_for)
record.respond_to?(:_timeliness_raw_value_for) &&
record._timeliness_raw_value_for(attr_name)
end
end
def timezone_aware?(record, attr_name)
@@ -86,4 +89,4 @@ module ValidatesTimeliness
end
# Compatibility with ActiveModel validates method which matches option keys to their validator class
TimelinessValidator = ValidatesTimeliness::Validator
ActiveModel::Validations::TimelinessValidator = ValidatesTimeliness::Validator

View File

@@ -1,3 +1,3 @@
module ValidatesTimeliness
VERSION = '3.0.0'
VERSION = '3.0.6'
end

View File

@@ -6,10 +6,12 @@ require 'active_record'
require 'action_view'
require 'timecop'
require 'rspec_tag_matchers'
require 'model_helpers'
require 'validates_timeliness'
require 'test_model'
require 'support/test_model'
require 'support/model_helpers'
require 'support/config_helper'
ValidatesTimeliness.setup do |c|
c.extend_orms = [ :active_record ]
@@ -75,11 +77,20 @@ class Employee < ActiveRecord::Base
validates_time :birth_time
validates_datetime :birth_datetime
define_attribute_methods
attr_accessor :redefined_birth_date_called
def birth_date=(value)
self.redefined_birth_date_called = true
super
end
end
Rspec.configure do |c|
c.mock_with :rspec
c.include(RspecTagMatchers)
c.include(ModelHelpers)
c.include(ConfigHelper)
c.before do
Person.reset_callbacks(:validate)
PersonWithShim.timeliness_validated_attributes = []

View File

@@ -0,0 +1,26 @@
module ConfigHelper
extend ActiveSupport::Concern
# Justin French tip
def with_config(preference_name, temporary_value)
old_value = ValidatesTimeliness.send(preference_name)
ValidatesTimeliness.send(:"#{preference_name}=", temporary_value)
yield
ensure
ValidatesTimeliness.send(:"#{preference_name}=", old_value)
end
module ClassMethods
def with_config(preference_name, temporary_value)
original_config_value = ValidatesTimeliness.send(preference_name)
before(:all) do
ValidatesTimeliness.send(:"#{preference_name}=", temporary_value)
end
after(:all) do
ValidatesTimeliness.send(:"#{preference_name}=", original_config_value)
end
end
end
end

View File

@@ -34,7 +34,15 @@ describe ValidatesTimeliness::AttributeMethods do
r._timeliness_raw_value_for(:birth_datetime).should == date_string
end
it 'should not overwrite user defined methods' do
e = Employee.new
e.birth_date = '2010-01-01'
e.redefined_birth_date_called.should be_true
end
context "with plugin parser" do
with_config(:use_plugin_parser, true)
class PersonWithParser
include TestModel
include TestModelShim
@@ -46,25 +54,12 @@ describe ValidatesTimeliness::AttributeMethods do
validates_datetime :birth_datetime
end
before :all do
ValidatesTimeliness.use_plugin_parser = true
end
it 'should parse a string value' do
Timeliness::Parser.should_receive(:parse)
r = PersonWithParser.new
r.birth_date = '2010-01-01'
end
it 'should parse string as current timezone' do
r = PersonWithParser.new
r.birth_datetime = '2010-01-01 12:00'
r.birth_datetime.zone == Time.zone.name
end
after :all do
ValidatesTimeliness.use_plugin_parser = false
end
end
end

View File

@@ -3,13 +3,13 @@ require 'spec_helper'
describe ValidatesTimeliness::Conversion do
include ValidatesTimeliness::Conversion
let(:options) { Hash.new }
before do
Timecop.freeze(Time.mktime(2010, 1, 1, 0, 0, 0))
end
describe "#type_cast_value" do
let(:options) { Hash.new }
describe "for date type" do
it "should return same value for date value" do
type_cast_value(Date.new(2010, 1, 1), :date).should == Date.new(2010, 1, 1)
@@ -22,6 +22,10 @@ describe ValidatesTimeliness::Conversion do
it "should return date part of datetime value" do
type_cast_value(DateTime.new(2010, 1, 1, 0, 0, 0), :date).should == Date.new(2010, 1, 1)
end
it 'should return nil for invalid value types' do
type_cast_value(12, :date).should == nil
end
end
describe "for time type" do
@@ -40,6 +44,10 @@ describe ValidatesTimeliness::Conversion do
it "should return dummy date with time part for datetime value" do
type_cast_value(DateTime.civil_from_format(:utc, 2010, 1, 1, 12, 34, 56), :time).should == Time.utc(2000, 1, 1, 12, 34, 56)
end
it 'should return nil for invalid value types' do
type_cast_value(12, :time).should == nil
end
end
describe "for datetime type" do
@@ -63,6 +71,10 @@ describe ValidatesTimeliness::Conversion do
result.should == Time.zone.local(2010, 1, 1, 23, 34, 56)
result.zone.should == 'EST'
end
it 'should return nil for invalid value types' do
type_cast_value(12, :datetime).should == nil
end
end
describe "ignore_usec option" do
@@ -102,17 +114,10 @@ describe ValidatesTimeliness::Conversion do
end
describe "with custom dummy date" do
before do
@original_dummy_date = ValidatesTimeliness.dummy_date_for_time_type
ValidatesTimeliness.dummy_date_for_time_type = [2010, 1, 1]
end
it 'should return dummy time with custom dummy date' do
dummy_time(Time.utc(1999, 11, 22, 12, 34, 56)).should == Time.utc(2010, 1, 1, 12, 34, 56)
end
after do
ValidatesTimeliness.dummy_date_for_time_type = @original_dummy_date
with_config(:dummy_date_for_time_type, [2010, 1, 1] ) do
dummy_time(Time.utc(1999, 11, 22, 12, 34, 56)).should == Time.utc(2010, 1, 1, 12, 34, 56)
end
end
end
end
@@ -194,4 +199,36 @@ describe ValidatesTimeliness::Conversion do
end
end
end
describe "#parse" do
context "use_plugin_parser setting is true" do
with_config(:use_plugin_parser, true)
it 'should use timeliness' do
Timeliness::Parser.should_receive(:parse)
parse('2000-01-01')
end
end
context "use_plugin_parser setting is false" do
with_config(:use_plugin_parser, false)
it 'should use Time.zone.parse attribute is timezone aware' do
@timezone_aware = true
Time.zone.should_receive(:parse)
parse('2000-01-01')
end
it 'should use value#to_time if use_plugin_parser setting is false and attribute is not timezone aware' do
@timezone_aware = false
value = '2000-01-01'
value.should_receive(:to_time)
parse(value)
end
end
it 'should return nil if value is nil' do
parse(nil).should be_nil
end
end
end

View File

@@ -4,9 +4,7 @@ describe ValidatesTimeliness::Extensions::DateTimeSelect do
include ActionView::Helpers::DateHelper
attr_reader :person, :params
before :all do
ValidatesTimeliness.use_plugin_parser = true
end
with_config(:use_plugin_parser, true)
before do
@person = Person.new
@@ -15,7 +13,7 @@ describe ValidatesTimeliness::Extensions::DateTimeSelect do
describe "datetime_select" do
it "should use param values when attribute is nil" do
params["person"] = {
@params["person"] = {
"birth_datetime(1i)" => 2009,
"birth_datetime(2i)" => 2,
"birth_datetime(3i)" => 29,
@@ -24,17 +22,12 @@ describe ValidatesTimeliness::Extensions::DateTimeSelect do
"birth_datetime(6i)" => 14,
}
person.birth_datetime = nil
output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
output.should have_tag('select[id=person_birth_datetime_1i] option[selected=selected]', '2009')
output.should have_tag('select[id=person_birth_datetime_2i] option[selected=selected]', 'February')
output.should have_tag('select[id=person_birth_datetime_3i] option[selected=selected]', '29')
output.should have_tag('select[id=person_birth_datetime_4i] option[selected=selected]', '12')
output.should have_tag('select[id=person_birth_datetime_5i] option[selected=selected]', '13')
output.should have_tag('select[id=person_birth_datetime_6i] option[selected=selected]', '14')
@output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
should_have_datetime_selected(:birth_datetime, :year => 2009, :month => 'February', :day => 29, :hour => 12, :min => 13, :sec => 14)
end
it "should override object values and use params if present" do
params["person"] = {
@params["person"] = {
"birth_datetime(1i)" => 2009,
"birth_datetime(2i)" => 2,
"birth_datetime(3i)" => 29,
@@ -43,100 +36,70 @@ describe ValidatesTimeliness::Extensions::DateTimeSelect do
"birth_datetime(6i)" => 14,
}
person.birth_datetime = "2010-01-01 15:16:17"
output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
output.should have_tag('select[id=person_birth_datetime_1i] option[selected=selected]', '2009')
output.should have_tag('select[id=person_birth_datetime_2i] option[selected=selected]', 'February')
output.should have_tag('select[id=person_birth_datetime_3i] option[selected=selected]', '29')
output.should have_tag('select[id=person_birth_datetime_4i] option[selected=selected]', '12')
output.should have_tag('select[id=person_birth_datetime_5i] option[selected=selected]', '13')
output.should have_tag('select[id=person_birth_datetime_6i] option[selected=selected]', '14')
@output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
should_have_datetime_selected(:birth_datetime, :year => 2009, :month => 'February', :day => 29, :hour => 12, :min => 13, :sec => 14)
end
it "should use attribute values from object if no params" do
person.birth_datetime = "2009-01-02 12:13:14"
output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
output.should have_tag('select[id=person_birth_datetime_1i] option[selected=selected]', '2009')
output.should have_tag('select[id=person_birth_datetime_2i] option[selected=selected]', 'January')
output.should have_tag('select[id=person_birth_datetime_3i] option[selected=selected]', '2')
output.should have_tag('select[id=person_birth_datetime_4i] option[selected=selected]', '12')
output.should have_tag('select[id=person_birth_datetime_5i] option[selected=selected]', '13')
output.should have_tag('select[id=person_birth_datetime_6i] option[selected=selected]', '14')
@output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
should_have_datetime_selected(:birth_datetime, :year => 2009, :month => 'January', :day => 2, :hour => 12, :min => 13, :sec => 14)
end
it "should use attribute values if params does not contain attribute params" do
person.birth_datetime = "2009-01-02 12:13:14"
params["person"] = { }
output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
output.should have_tag('select[id=person_birth_datetime_1i] option[selected=selected]', '2009')
output.should have_tag('select[id=person_birth_datetime_2i] option[selected=selected]', 'January')
output.should have_tag('select[id=person_birth_datetime_3i] option[selected=selected]', '2')
output.should have_tag('select[id=person_birth_datetime_4i] option[selected=selected]', '12')
output.should have_tag('select[id=person_birth_datetime_5i] option[selected=selected]', '13')
output.should have_tag('select[id=person_birth_datetime_6i] option[selected=selected]', '14')
@params["person"] = { }
@output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
should_have_datetime_selected(:birth_datetime, :year => 2009, :month => 'January', :day => 2, :hour => 12, :min => 13, :sec => 14)
end
it "should not select values when attribute value is nil and has no param values" do
person.birth_datetime = nil
output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
output.should_not have_tag('select[id=person_birth_datetime_1i] option[selected=selected]')
output.should_not have_tag('select[id=person_birth_datetime_2i] option[selected=selected]')
output.should_not have_tag('select[id=person_birth_datetime_3i] option[selected=selected]')
output.should_not have_tag('select[id=person_birth_datetime_4i] option[selected=selected]')
output.should_not have_tag('select[id=person_birth_datetime_5i] option[selected=selected]')
output.should_not have_tag('select[id=person_birth_datetime_6i] option[selected=selected]')
@output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
should_not_have_datetime_selected(:birth_datetime, :year, :month, :day, :hour, :min, :sec)
end
end
describe "date_select" do
it "should use param values when attribute is nil" do
params["person"] = {
@params["person"] = {
"birth_date(1i)" => 2009,
"birth_date(2i)" => 2,
"birth_date(3i)" => 29,
}
person.birth_date = nil
output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true)
output.should have_tag('select[id=person_birth_date_1i] option[selected=selected]', '2009')
output.should have_tag('select[id=person_birth_date_2i] option[selected=selected]', 'February')
output.should have_tag('select[id=person_birth_date_3i] option[selected=selected]', '29')
@output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true)
should_have_datetime_selected(:birth_date, :year => 2009, :month => 'February', :day => 29)
end
it "should override object values and use params if present" do
params["person"] = {
@params["person"] = {
"birth_date(1i)" => 2009,
"birth_date(2i)" => 2,
"birth_date(3i)" => 29,
}
person.birth_date = "2009-03-01"
output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true)
output.should have_tag('select[id=person_birth_date_1i] option[selected=selected]', '2009')
output.should have_tag('select[id=person_birth_date_2i] option[selected=selected]', 'February')
output.should have_tag('select[id=person_birth_date_3i] option[selected=selected]', '29')
@output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true)
should_have_datetime_selected(:birth_date, :year => 2009, :month => 'February', :day => 29)
end
it "should select attribute values from object if no params" do
person.birth_date = "2009-01-02"
output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true)
output.should have_tag('select[id=person_birth_date_1i] option[selected=selected]', '2009')
output.should have_tag('select[id=person_birth_date_2i] option[selected=selected]', 'January')
output.should have_tag('select[id=person_birth_date_3i] option[selected=selected]', '2')
@output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true)
should_have_datetime_selected(:birth_date, :year => 2009, :month => 'January', :day => 2)
end
it "should select attribute values if params does not contain attribute params" do
person.birth_date = "2009-01-02"
params["person"] = { }
output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true)
output.should have_tag('select[id=person_birth_date_1i] option[selected=selected]', '2009')
output.should have_tag('select[id=person_birth_date_2i] option[selected=selected]', 'January')
output.should have_tag('select[id=person_birth_date_3i] option[selected=selected]', '2')
@params["person"] = { }
@output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true)
should_have_datetime_selected(:birth_date, :year => 2009, :month => 'January', :day => 2)
end
it "should not select values when attribute value is nil and has no param values" do
person.birth_date = nil
output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true)
output.should_not have_tag('select[id=person_birth_date_1i] option[selected=selected]')
output.should_not have_tag('select[id=person_birth_date_2i] option[selected=selected]')
output.should_not have_tag('select[id=person_birth_date_3i] option[selected=selected]')
@output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true)
should_not_have_datetime_selected(:birth_time, :year, :month, :day)
end
end
@@ -146,7 +109,7 @@ describe ValidatesTimeliness::Extensions::DateTimeSelect do
end
it "should use param values when attribute is nil" do
params["person"] = {
@params["person"] = {
"birth_time(1i)" => 2000,
"birth_time(2i)" => 1,
"birth_time(3i)" => 1,
@@ -155,30 +118,34 @@ describe ValidatesTimeliness::Extensions::DateTimeSelect do
"birth_time(6i)" => 14,
}
person.birth_time = nil
output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true)
output.should have_tag('select[id=person_birth_time_4i] option[selected=selected]', '12')
output.should have_tag('select[id=person_birth_time_5i] option[selected=selected]', '13')
output.should have_tag('select[id=person_birth_time_6i] option[selected=selected]', '14')
@output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true)
should_have_datetime_selected(:birth_time, :hour => 12, :min => 13, :sec => 14)
end
it "should select attribute values from object if no params" do
person.birth_time = "2000-01-01 12:13:14"
output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true)
output.should have_tag('select[id=person_birth_time_4i] option[selected=selected]', '12')
output.should have_tag('select[id=person_birth_time_5i] option[selected=selected]', '13')
output.should have_tag('select[id=person_birth_time_6i] option[selected=selected]', '14')
@output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true)
should_have_datetime_selected(:birth_time, :hour => 12, :min => 13, :sec => 14)
end
it "should not select values when attribute value is nil and has no param values" do
person.birth_time = nil
output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true)
output.should_not have_tag('select[id=person_birth_time_4i] option[selected=selected]')
output.should_not have_tag('select[id=person_birth_time_5i] option[selected=selected]')
output.should_not have_tag('select[id=person_birth_time_6i] option[selected=selected]')
@output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true)
should_not_have_datetime_selected(:birth_time, :hour, :min, :sec)
end
end
after :all do
ValidatesTimeliness.use_plugin_parser = false
def should_have_datetime_selected(field, datetime_hash)
datetime_hash.each do |key, value|
index = {:year => 1, :month => 2, :day => 3, :hour => 4, :min => 5, :sec => 6}[key]
@output.should have_tag("select[id=person_#{field}_#{index}i] option[selected=selected]", value.to_s)
end
end
def should_not_have_datetime_selected(field, *attributes)
attributes.each do |attribute|
index = {:year => 1, :month => 2, :day => 3, :hour => 4, :min => 5, :sec => 6}[attribute]
@output.should_not have_tag("select[id=person_#{attribute}_#{index}i] option[selected=selected]")
end
end
end

View File

@@ -3,19 +3,31 @@ require 'spec_helper'
describe ValidatesTimeliness::Extensions::MultiparameterHandler do
let(:employee) { Employee.new }
it 'should return string value for invalid dates' do
instantiate_time_object('birth_date', [2000, 2, 31]).should == '2000-02-31'
context "time column" do
it 'should return string value for invalid date portion' do
multiparameter_attribute(:birth_datetime, [2000, 2, 31, 12, 0, 0])
employee.birth_datetime_before_type_cast.should == '2000-02-31 12:00:00'
end
it 'should return Time value for valid datetimes' do
multiparameter_attribute(:birth_datetime, [2000, 2, 28, 12, 0, 0])
employee.birth_datetime_before_type_cast.should be_kind_of(Time)
end
end
it 'should return string value for invalid datetimes' do
instantiate_time_object('birth_datetime', [2000, 2, 31, 12, 0, 0]).should == '2000-02-31 12:00:00'
end
it 'should return Time value for valid datetimes' do
instantiate_time_object('birth_datetime', [2000, 2, 28, 12, 0, 0]).should be_kind_of(Time)
context "date column" do
it 'should return string value for invalid date' do
multiparameter_attribute(:birth_date, [2000, 2, 31])
employee.birth_date_before_type_cast.should == '2000-02-31'
end
it 'should return Date value for valid date' do
multiparameter_attribute(:birth_date, [2000, 2, 28])
employee.birth_date_before_type_cast.should be_kind_of(Date)
end
end
def instantiate_time_object(name, values)
employee.send(:instantiate_time_object, name, values)
def multiparameter_attribute(name, values)
employee.send(:execute_callstack_for_multiparameter_attributes, name.to_s => values)
end
end

View File

@@ -33,31 +33,46 @@ describe ValidatesTimeliness, 'ActiveRecord' do
end
context "with plugin parser" do
with_config(:use_plugin_parser, true)
class EmployeeWithParser < ActiveRecord::Base
set_table_name 'employees'
validates_date :birth_date
validates_datetime :birth_datetime
end
before :all do
ValidatesTimeliness.use_plugin_parser = true
end
it 'should parse a string value' do
Timeliness::Parser.should_receive(:parse)
r = EmployeeWithParser.new
r.birth_date = '2010-01-01'
end
it 'should parse string as current timezone' do
r = EmployeeWithParser.new
r.birth_datetime = '2010-06-01 12:00'
r.birth_datetime.utc_offset.should == 10.hours
context "for a date column" do
it 'should store a date value after parsing string' do
r = EmployeeWithParser.new
r.birth_date = '2010-01-01'
r.birth_date.should be_kind_of(Date)
r.birth_date.should == Date.new(2010, 1, 1)
end
end
after :all do
Time.zone = 'Australia/Melbourne'
ValidatesTimeliness.use_plugin_parser = false
context "for a datetime column" do
with_config(:default_timezone, 'Australia/Melbourne')
it 'should parse string into Time value' do
r = EmployeeWithParser.new
r.birth_datetime = '2010-01-01 12:00'
r.birth_datetime.should be_kind_of(Time)
end
it 'should parse string as current timezone' do
r = EmployeeWithParser.new
r.birth_datetime = '2010-06-01 12:00'
r.birth_datetime.utc_offset.should == Time.zone.utc_offset
end
end
end
end

View File

@@ -12,20 +12,20 @@ Mongoid.configure do |config|
config.persist_in_safe_mode = false
end
class Article
::ValidatesTimeliness.use_plugin_parser = true
include Mongoid::Document
field :publish_date, :type => Date
field :publish_time, :type => Time
field :publish_datetime, :type => DateTime
validates_date :publish_date, :allow_nil => true
validates_time :publish_time, :allow_nil => true
validates_datetime :publish_datetime, :allow_nil => true
::ValidatesTimeliness.use_plugin_parser = false
end
describe ValidatesTimeliness, 'Mongoid' do
class Article
::ValidatesTimeliness.use_plugin_parser = true
include Mongoid::Document
field :publish_date, :type => Date
field :publish_time, :type => Time
field :publish_datetime, :type => DateTime
validates_date :publish_date, :allow_nil => true
validates_time :publish_time, :allow_nil => true
validates_datetime :publish_datetime, :allow_nil => true
::ValidatesTimeliness.use_plugin_parser = false
end
context "validation methods" do
it 'should be defined on the class' do
Article.should respond_to(:validates_date)
@@ -52,9 +52,7 @@ describe ValidatesTimeliness, 'Mongoid' do
end
context "with plugin parser" do
before :all do
ValidatesTimeliness.use_plugin_parser = true
end
with_config(:use_plugin_parser, false)
it 'should parse a string value' do
Timeliness::Parser.should_receive(:parse)
@@ -62,14 +60,24 @@ describe ValidatesTimeliness, 'Mongoid' do
r.publish_date = '2010-01-01'
end
it 'should parse string into Time value' do
r = Article.new
r.publish_datetime = '2010-01-01 12:00'
r.publish_datetime.should == Time.utc(2010,1,1,12,0)
context "for a date column" do
it 'should store a date value after parsing string' do
r = Article.new
r.publish_date = '2010-01-01'
r.publish_date.should be_kind_of(Date)
r.publish_date.should == Date.new(2010, 1, 1)
end
end
after :all do
ValidatesTimeliness.use_plugin_parser = false
context "for a datetime column" do
it 'should parse string into Time value' do
r = Article.new
r.publish_datetime = '2010-01-01 12:00'
r.publish_datetime.should be_kind_of(Time)
r.publish_datetime.should == Time.utc(2010,1,1,12,0)
end
end
end
end
@@ -85,7 +93,7 @@ describe ValidatesTimeliness, 'Mongoid' do
context "before_type_cast method" do
it 'should not be defined if ORM does not support it' do
Article.new.should_not respond_to(:birth_datetime_before_type_cast)
Article.new.should_not respond_to(:publish_datetime_before_type_cast)
end
end
end

View File

@@ -1,8 +1,6 @@
require 'spec_helper'
describe ValidatesTimeliness::Validator, ":after option" do
include ModelHelpers
describe "for date type" do
before do
Person.validates_date :birth_date, :after => Date.new(2010, 1, 1)

View File

@@ -1,8 +1,6 @@
require 'spec_helper'
describe ValidatesTimeliness::Validator, ":before option" do
include ModelHelpers
describe "for date type" do
before do
Person.validates_date :birth_date, :before => Date.new(2010, 1, 1)

View File

@@ -1,8 +1,6 @@
require 'spec_helper'
describe ValidatesTimeliness::Validator, ":is_at option" do
include ModelHelpers
before do
Timecop.freeze(Time.local_time(2010, 1, 1, 0, 0, 0))
end

View File

@@ -1,8 +1,6 @@
require 'spec_helper'
describe ValidatesTimeliness::Validator, ":on_or_after option" do
include ModelHelpers
describe "for date type" do
before do
Person.validates_date :birth_date, :on_or_after => Date.new(2010, 1, 1)

View File

@@ -1,8 +1,6 @@
require 'spec_helper'
describe ValidatesTimeliness::Validator, ":on_or_before option" do
include ModelHelpers
describe "for date type" do
before do
Person.validates_date :birth_date, :on_or_before => Date.new(2010, 1, 1)

View File

@@ -1,21 +1,16 @@
require 'spec_helper'
describe ValidatesTimeliness::Validator do
include ModelHelpers
NIL = [nil]
before do
Timecop.freeze(Time.local_time(2010, 1, 1, 0, 0, 0))
end
it 'should return validator kind as :timeliness' do
ValidatesTimeliness::Validator.kind.should == :timeliness
end
describe "Model.validates :timeliness option" do
describe "Model.validates with :timeliness option" do
it 'should use plugin validator class' do
Person.validates :birth_date, :timeliness => {:is_at => Date.new(2010,1,1), :type => :date}
Person.validators.should have(1).kind_of(TimelinessValidator)
Person.validators.should have(1).kind_of(ActiveModel::Validations::TimelinessValidator)
invalid!(:birth_date, Date.new(2010,1,2))
valid!(:birth_date, Date.new(2010,1,1))
end
@@ -70,18 +65,26 @@ describe ValidatesTimeliness::Validator do
describe "array value" do
it 'should be split option into :on_or_after and :on_or_before values' do
on_or_after, on_or_before = Date.new(2010,1,1), Date.new(2010,1,2)
Person.validates_time :birth_date, :between => [on_or_after, on_or_before]
Person.validates_date :birth_date, :between => [on_or_after, on_or_before]
Person.validators.first.options[:on_or_after].should == on_or_after
Person.validators.first.options[:on_or_before].should == on_or_before
invalid!(:birth_date, on_or_after - 1, "must be on or after 2010-01-01")
invalid!(:birth_date, on_or_before + 1, "must be on or before 2010-01-02")
valid!(:birth_date, on_or_after)
valid!(:birth_date, on_or_before)
end
end
describe "range value" do
it 'should be split option into :on_or_after and :on_or_before values' do
on_or_after, on_or_before = Date.new(2010,1,1), Date.new(2010,1,2)
Person.validates_time :birth_date, :between => on_or_after..on_or_before
Person.validates_date :birth_date, :between => on_or_after..on_or_before
Person.validators.first.options[:on_or_after].should == on_or_after
Person.validators.first.options[:on_or_before].should == on_or_before
invalid!(:birth_date, on_or_after - 1, "must be on or after 2010-01-01")
invalid!(:birth_date, on_or_before + 1, "must be on or before 2010-01-02")
valid!(:birth_date, on_or_after)
valid!(:birth_date, on_or_before)
end
end
end
@@ -110,9 +113,7 @@ describe ValidatesTimeliness::Validator do
let(:person) { PersonWithFormatOption.new }
before(:all) do
ValidatesTimeliness.use_plugin_parser = true
end
with_config(:use_plugin_parser, true)
it "should be valid when value matches format" do
person.birth_date = '11-12-1913'
@@ -125,33 +126,34 @@ describe ValidatesTimeliness::Validator do
person.valid?
person.errors[:birth_date].should include('is not a valid date')
end
after(:all) do
ValidatesTimeliness.use_plugin_parser = false
end
end
describe "restriction value errors" do
let(:person) { Person.new(:birth_date => Date.today) }
before do
Person.validates_time :birth_date, :is_at => lambda { raise }
Person.validates_time :birth_date, :is_at => lambda { raise }, :before => lambda { raise }
end
it "should be added when ignore_restriction_errors is false" do
ValidatesTimeliness.ignore_restriction_errors = false
person.valid?
person.errors[:birth_date].first.should match("Error occurred validating birth_date for :is_at restriction")
with_config(:ignore_restriction_errors, false) do
person.valid?
person.errors[:birth_date].first.should match("Error occurred validating birth_date for :is_at restriction")
end
end
it "should not be added when ignore_restriction_errors is true" do
ValidatesTimeliness.ignore_restriction_errors = true
person.valid?
person.errors[:birth_date].should be_empty
with_config(:ignore_restriction_errors, true) do
person.valid?
person.errors[:birth_date].should be_empty
end
end
after :all do
ValidatesTimeliness.ignore_restriction_errors = false
it 'should exit on first error' do
with_config(:ignore_restriction_errors, false) do
person.valid?
person.errors[:birth_date].should have(1).items
end
end
end

View File

@@ -1,32 +1,20 @@
# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
require "validates_timeliness/version"
Gem::Specification.new do |s|
s.name = %q{validates_timeliness}
s.version = "3.0.0"
s.name = "validates_timeliness"
s.version = ValidatesTimeliness::VERSION
s.authors = ["Adam Meehan"]
s.summary = %q{Date and time validation plugin for Rails which allows custom formats}
s.description = %q{Adds validation methods to ActiveModel for validating dates and times. Works with multiple ORMS.}
s.email = %q{adam.meehan@gmail.com}
s.homepage = %q{http://github.com/adzap/validates_timeliness}
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Adam Meehan"]
s.date = %q{2010-10-18}
s.description = %q{Date and time validation plugin for Rails which allows custom formats}
s.email = %q{adam.meehan@gmail.com}
s.require_paths = ["lib"]
s.files = `git ls-files`.split("\n") - %w{ .gitignore .rspec Gemfile Gemfile.lock autotest/discover.rb }
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.extra_rdoc_files = ["README.rdoc", "CHANGELOG.rdoc", "LICENSE"]
s.files = ["validates_timeliness.gemspec", "LICENSE", "CHANGELOG.rdoc", "README.rdoc", "Rakefile", "lib/generators", "lib/generators/validates_timeliness", "lib/generators/validates_timeliness/install_generator.rb", "lib/generators/validates_timeliness/templates", "lib/generators/validates_timeliness/templates/en.yml", "lib/generators/validates_timeliness/templates/validates_timeliness.rb", "lib/validates_timeliness", "lib/validates_timeliness/attribute_methods.rb", "lib/validates_timeliness/conversion.rb", "lib/validates_timeliness/extensions", "lib/validates_timeliness/extensions/date_time_select.rb", "lib/validates_timeliness/extensions/multiparameter_handler.rb", "lib/validates_timeliness/extensions.rb", "lib/validates_timeliness/helper_methods.rb", "lib/validates_timeliness/orm", "lib/validates_timeliness/orm/active_record.rb", "lib/validates_timeliness/orm/mongoid.rb", "lib/validates_timeliness/railtie.rb", "lib/validates_timeliness/validator.rb", "lib/validates_timeliness/version.rb", "lib/validates_timeliness.rb", "spec/model_helpers.rb", "spec/spec_helper.rb", "spec/test_model.rb", "spec/validates_timeliness", "spec/validates_timeliness/attribute_methods_spec.rb", "spec/validates_timeliness/conversion_spec.rb", "spec/validates_timeliness/extensions", "spec/validates_timeliness/extensions/date_time_select_spec.rb", "spec/validates_timeliness/extensions/multiparameter_handler_spec.rb", "spec/validates_timeliness/helper_methods_spec.rb", "spec/validates_timeliness/orm", "spec/validates_timeliness/orm/active_record_spec.rb", "spec/validates_timeliness/orm/mongoid_spec.rb", "spec/validates_timeliness/validator", "spec/validates_timeliness/validator/after_spec.rb", "spec/validates_timeliness/validator/before_spec.rb", "spec/validates_timeliness/validator/is_at_spec.rb", "spec/validates_timeliness/validator/on_or_after_spec.rb", "spec/validates_timeliness/validator/on_or_before_spec.rb", "spec/validates_timeliness/validator_spec.rb", "spec/validates_timeliness_spec.rb"]
s.homepage = %q{http://github.com/adzap/validates_timeliness}
s.require_paths = ["lib"]
s.rubyforge_project = %q{validates_timeliness}
s.rubygems_version = %q{1.3.7}
s.summary = %q{Date and time validation plugin for Rails which allows custom formats}
if s.respond_to? :specification_version then
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 3
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<timeliness>, ["~> 0.1.0"])
else
s.add_dependency(%q<timeliness>, ["~> 0.1.0"])
end
else
s.add_dependency(%q<timeliness>, ["~> 0.1.0"])
end
s.add_runtime_dependency(%q<timeliness>, ["~> 0.3.3"])
end