Compare commits

..

71 Commits

Author SHA1 Message Date
Adam Meehan
b6acda539f v3.0.10 2012-03-29 13:45:40 +11:00
Adam Meehan
4aa20bb002 Stricter method signature for _timeliness_raw_value_for to take string
Add basic validation specs to each ORM shim
2012-03-29 13:00:28 +11:00
Adam Meehan
df12d6dad0 v3.0.9 2012-03-26 22:00:12 +11:00
Adam Meehan
f11255a7a3 Fix multiparameter extension to not allow partial dates as per ActiveRecord implementation. 2012-03-26 20:22:09 +11:00
Adam Meehan
a6a3dff4d4 Revert "Move AR railtie hook outside of initializer to avoid late inclusion of shim"
This reverts commit 48fd72ae5b.
2012-02-24 11:52:58 +11:00
Adam Meehan
ff594d5873 Tighten up mongoid shim for reload override in 1.8.x and 1.9.x 2012-02-06 22:48:29 +11:00
Adam Meehan
8c1ba048df Refactor timeliness method definition 2012-02-06 22:47:08 +11:00
Adam Meehan
48fd72ae5b Move AR railtie hook outside of initializer to avoid late inclusion of shim 2012-02-06 22:45:01 +11:00
Adam Meehan
43f49076fb Changed multiparameter implementation to be more like AR 3.1 but backwards compatible
Specs improved to not make direct call to multiparameter method.
2012-02-02 09:00:14 +11:00
Chris Griego
64a7440de4 Fix multiparameter extension to work with ActiveRecord 3.1 2012-02-02 08:54:39 +11:00
Chris Griego
2702ec3266 The ActiveRecord extension now returns the original return value for .define_attribute_methods
This helps other extensions, like PermalinkFu, which depend on the return value
2012-02-02 08:44:22 +11:00
Adam Meehan
20549c7acd Setup bundler in the rake file 2012-02-01 21:30:57 +11:00
Adam Meehan
4acd0180f9 Add specs for allow_nil and allow_blank with attribute value cache active 2012-02-01 21:25:42 +11:00
Adam Meehan
3f4615e053 scope a spec to AR version 2012-02-01 21:25:05 +11:00
Adam Meehan
84316bc73a Refactor AR shim for v3.1 checks 2012-02-01 21:24:38 +11:00
Adam Meehan
5be45b00db Hook into undefine_attributes_methods to remove timeliness methods as well 2012-02-01 20:38:05 +11:00
Adam Meehan
f8aeeca0a9 A fix for ActiveRecord 3.1.x and plugin parser not working together (issue #52) 2012-01-26 22:44:01 +11:00
Adam Meehan
f5e2deeb73 Add credit in changelog 2011-12-24 17:53:07 +11:00
Adam Meehan
acd10f7b64 v3.0.8 2011-12-24 17:50:22 +11:00
Adam Meehan
68b2579ca0 Merge pull request #61 from carlosantoniodasilva/rails-3.2-deprecation-warnings
Remove deprecated InstanceMethods module when using AS::Concern
2011-12-22 23:00:25 -08:00
Carlos Antonio da Silva
7a784a6c54 Remove InstanceMethods module when using AS::Concern, as it was deprecated in 3.2 2011-12-20 20:52:33 -02:00
Adam Meehan
907fd3e439 Fix for Mongoid shim for reload which was nicely moved into a module to allow super 2011-12-10 17:46:35 +11:00
Adam Meehan
e44e9d2f11 v3.0.7 2011-09-21 21:41:01 +10:00
Adam Meehan
86b7bc4829 Fix before_type_cast for non-dirty attributes (issue #52).
Only use before_type_cast implementation if earlier than 3.1.0 which has
it's own working version for date/time fields now.
2011-09-21 21:28:53 +10:00
Adam Meehan
34824bbbab Specs against rails 3.1.0 2011-09-18 18:56:06 +10:00
Adam Meehan
11ae94cba6 Cleanup DateTimeSelect extension specs 2011-09-18 18:53:38 +10:00
Adam Meehan
473da0fa5e Fix DateTimeSelect extension for Rails 3.1.0 2011-09-18 18:37:01 +10:00
Adam Meehan
e7b503ae4f Fix DateTimeSelect extension to use integers from param values.
Change extension spec to use string params.
2011-09-18 18:34:23 +10:00
Adam Meehan
af9d6cdba4 Fix brokena and brittle tests 2011-09-18 18:33:30 +10:00
Adam Meehan
9a99c47323 Can use simple Mongoid inclusion now that fixed Concern usage is released (a while ago) 2011-09-18 18:33:29 +10:00
Adam Meehan
fbc2867197 Remove Gemfile.lock from source and ignore 2011-09-18 18:33:29 +10:00
Adam Meehan
969edfcb83 Helper method spec 2011-09-18 18:33:29 +10:00
Adam Meehan
1faf0efa4b Spec helper validate method setup in test models not needed 2011-09-18 18:33:29 +10:00
Adam Meehan
2b53d713bc Merge pull request #45 from trusche/master
Add support for :discard_day option in DateTimeSelect extension
2011-09-18 01:32:08 -07:00
Thilo Rusche
ac90ab96cd fixed integer vs string expectation 2011-05-13 17:47:59 +01:00
Thilo Rusche
b4c1a39343 added support for :discard_day in form helpers 2011-05-13 17:13:11 +01:00
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
33 changed files with 843 additions and 575 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
pkg/
.bundle/
.rvmrc
Gemfile.lock

View File

@@ -1,3 +1,43 @@
= 3.0.10 [2012-03-26]
* Fix for ActiveRecord shim and validation with :allow_blank => true in AR 3.1+. Fixes issue#52.
= 3.0.9 [2012-03-26]
* ActiveRecord 3.1+ suport
* Fixes for multiparameter extension with empty date values (thanks @mogox, @Sharagoz)
= 3.0.8 [2011-12-24]
* Remove deprecated InstanceMethods module when using AS::Concern (carlosantoniodasilva)
* Update Mongoid shim for v2.3 compatability.
= 3.0.7 [2011-09-21]
* Fix ActiveRecord before_type_cast extension for non-dirty attributes.
* Don't override AR before_type_cast for >= 3.1.0 which now has it's own implementation for date/time attributes.
* Fix DateTimeSelect extension to convert params to integers (#45)
* Add #change method to DateTimeSelect extension (@trusche, #45)
* Cleanup Mongoid shim.
= 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.

25
Gemfile
View File

@@ -1,16 +1,21 @@
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 'rails', '~> 3.2.1'
gem 'rspec', '~> 2.8'
gem 'rspec-rails', '~> 2.8'
gem 'timecop'
gem 'rspec_tag_matchers'
gem 'ruby-debug'
gem 'ruby-debug', :platforms => [:ruby_18, :jruby]
gem 'ruby-debug19', :platforms => [:ruby_19]
group :mongoid do
gem 'mongoid', '~> 2.3.0'
gem 'bson_ext'
gem 'system_timer', :platforms => [:ruby_18]
end
group :active_record do
gem 'sqlite3-ruby', :require => 'sqlite3'
end

View File

@@ -1,120 +0,0 @@
GEM
remote: http://rubygems.org/
specs:
ZenTest (4.4.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)
builder (~> 2.1.2)
erubis (~> 2.6.6)
i18n (~> 0.4.1)
rack (~> 1.2.1)
rack-mount (~> 0.6.12)
rack-test (~> 0.5.4)
tzinfo (~> 0.3.23)
activemodel (3.0.0)
activesupport (= 3.0.0)
builder (~> 2.1.2)
i18n (~> 0.4.1)
activerecord (3.0.0)
activemodel (= 3.0.0)
activesupport (= 3.0.0)
arel (~> 1.0.0)
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)
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)
activesupport (>= 2.3.6)
mime-types
treetop (>= 1.4.5)
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)
tzinfo (~> 0.3.22)
will_paginate (~> 3.0.pre)
nokogiri (1.4.3.1)
polyglot (0.3.1)
rack (1.2.1)
rack-mount (0.6.13)
rack (>= 1.0.0)
rack-test (0.5.4)
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)
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_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)
timecop (0.3.5)
timeliness (0.1.1)
treetop (1.4.8)
polyglot (>= 0.3.1)
tzinfo (0.3.23)
will_paginate (3.0.pre2)
PLATFORMS
ruby
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)
rspec_tag_matchers
ruby-debug
sqlite3-ruby
timecop
timeliness (~> 0.1.1)

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,13 @@
require 'rubygems'
require 'bundler'
Bundler::GemHelper.install_tasks
Bundler.setup
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 +24,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
@@ -20,50 +20,73 @@ module ValidatesTimeliness
:datetime
end
def undefine_attribute_methods
super
undefine_timeliness_attribute_methods
end
protected
def define_timeliness_methods(before_type_cast=false)
return if timeliness_validated_attributes.blank?
timeliness_validated_attributes.each do |attr_name|
define_attribute_timeliness_methods(attr_name, before_type_cast)
end
end
def define_attribute_timeliness_methods(attr_name, before_type_cast=false)
define_timeliness_write_method(attr_name)
define_timeliness_before_type_cast_method(attr_name) if before_type_cast
end
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)
original_value = 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 }
super
@timeliness_cache["#{attr_name}"] = original_value
#{ "if value.is_a?(String)\n#{timeliness_type_cast_code(attr_name, 'value')}\nend" if ValidatesTimeliness.use_plugin_parser }
super(value)
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)
method_body, line = <<-EOV, __LINE__ + 1
def #{attr_name}_before_type_cast
_timeliness_raw_value_for('#{attr_name}')
_timeliness_raw_value_for('#{attr_name}') || @attributes['#{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
def undefine_timeliness_attribute_methods
generated_timeliness_methods.module_eval do
instance_methods.each { |m| undef_method(m) }
end
end
end
module InstanceMethods
def _timeliness_raw_value_for(attr_name)
@timeliness_cache && @timeliness_cache[attr_name.to_s]
@timeliness_cache && @timeliness_cache[attr_name]
end
def _clear_timeliness_cache
@timeliness_cache = {}
end
end
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

@@ -13,9 +13,25 @@ module ValidatesTimeliness
alias_method_chain :value, :timeliness
end
module InstanceMethods
class TimelinessDateTime
attr_accessor :year, :month, :day, :hour, :min, :sec
TimelinessDateTime = Struct.new(:year, :month, :day, :hour, :min, :sec)
def initialize(year, month, day, hour, min, sec)
@year, @month, @day, @hour, @min, @sec = year, month, day, hour, min, sec
end
# adapted from activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 36 (3.0.7)
def change(options)
TimelinessDateTime.new(
options[:year] || year,
options[:month] || month,
options[:day] || day,
options[:hour] || hour,
options[:min] || (options[:hour] ? 0 : min),
options[:sec] || ((options[:hour] || options[:min]) ? 0 : sec)
)
end
end
def datetime_selector_with_timeliness(*args)
@timeliness_date_or_time_tag = true
@@ -27,19 +43,19 @@ module ValidatesTimeliness
return value_without_timeliness(object)
end
@template_object.params[@object_name]
pairs = @template_object.params[@object_name].select {|k,v| k =~ /^#{@method_name}\(/ }
return value_without_timeliness(object) if pairs.empty?
values = [nil] * 6
pairs.map do |(param, value)|
position = param.scan(/\(([0-9]*).*\)/).first.first
values[position.to_i-1] = value
position = param.scan(/\((\d+)\w+\)/).first.first
values[position.to_i-1] = value.to_i
end
TimelinessDateTime.new(*values)
end
end
end
end
end

View File

@@ -3,26 +3,75 @@ 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 :execute_callstack_for_multiparameter_attributes, :execute_callstack_for_multiparameter_attributes_with_timeliness
alias_method :read_value_from_parameter, :read_value_from_parameter_with_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])
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?
return value
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)
validate_multiparameter_date_values(values) {
instantiate_time_object_without_timeliness(name, values)
}
end
def instantiate_date_object(name, values)
validate_multiparameter_date_values(values) {
Date.new(*values)
}
end
# Yield if date values are valid
def validate_multiparameter_date_values(values)
if values[0..2].all?{ |v| v.present? } && Date.valid_civil?(*values[0..2])
yield
else
Time.time_with_datetime_fallback(self.class.default_timezone, *values)
invalid_multiparameter_date_or_time_as_string(values)
end
end
def read_value_from_parameter_with_timeliness(name, values_from_param)
klass = (self.class.reflect_on_aggregation(name.to_sym) || column_for_attribute(name)).klass
values = values_from_param.is_a?(Hash) ? values_from_param.to_a.sort_by(&:first).map(&:last) : values_from_param
if values.empty? || values.all?{ |v| v.nil? }
nil
elsif klass == Time
instantiate_time_object(name, values)
elsif klass == Date
instantiate_date_object(name, values)
else
if respond_to?(:read_other_parameter_value)
read_date_parameter_value(name, values_from_param)
else
klass.new(*values)
end
end
end
def execute_callstack_for_multiparameter_attributes_with_timeliness(callstack)
errors = []
callstack.each do |name, values_with_empty_parameters|
begin
send(name + "=", read_value_from_parameter(name, values_with_empty_parameters))
rescue => ex
values = values_with_empty_parameters.is_a?(Hash) ? values_with_empty_parameters.values : values_with_empty_parameters
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

@@ -3,13 +3,22 @@ module ValidatesTimeliness
module ActiveRecord
extend ActiveSupport::Concern
module ClassMethods
def define_attribute_methods
super
# Define write method and before_type_cast method
define_timeliness_methods(true)
def self.use_plugin_cache?
::ActiveRecord::VERSION::STRING < '3.1.0'
end
included do
if ValidatesTimeliness::ORM::ActiveRecord.use_plugin_cache?
include Reload
else
# Just use the built-in before_type_cast retrieval
alias_method :_timeliness_raw_value_for, :read_attribute_before_type_cast
end
end
module ClassMethods
public
def timeliness_attribute_timezone_aware?(attr_name)
attr_name = attr_name.to_s
create_time_zone_conversion_attribute?(attr_name, columns_hash[attr_name])
@@ -18,9 +27,47 @@ module ValidatesTimeliness
def timeliness_attribute_type(attr_name)
columns_hash[attr_name.to_s].type
end
def define_attribute_methods
super.tap do |attribute_methods_generated|
use_before_type_cast = ValidatesTimeliness::ORM::ActiveRecord.use_plugin_cache?
define_timeliness_methods use_before_type_cast
end
end
module InstanceMethods
protected
def define_attribute_timeliness_methods(attr_name, before_type_cast=false)
if before_type_cast
define_timeliness_write_method(attr_name)
define_timeliness_before_type_cast_method(attr_name)
elsif ValidatesTimeliness.use_plugin_parser
define_timeliness_write_method_without_cache(attr_name)
end
end
def define_timeliness_write_method_without_cache(attr_name)
method_body, line = <<-EOV, __LINE__ + 1
def #{attr_name}=(value)
original_value = value
if value.is_a?(String)\n#{timeliness_type_cast_code(attr_name, 'value')}\nend
super(value)
@attributes['#{attr_name}'] = original_value
end
EOV
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)
method_body = super
method_body << "\n#{var_name} = #{var_name}.to_date if #{var_name}" if type == :date
method_body
end
end
module Reload
def reload(*args)
_clear_timeliness_cache
super

View File

@@ -7,6 +7,8 @@ module ValidatesTimeliness
# field value in Mongoid. Parser will return nil rather than error.
module ClassMethods
public
# Mongoid has no bulk attribute method definition hook. It defines
# them with each field definition. So we likewise define them after
# each validation is defined.
@@ -16,19 +18,6 @@ module ValidatesTimeliness
attr_names.each { |attr_name| define_timeliness_write_method(attr_name) }
end
def define_timeliness_write_method(attr_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)
end
def timeliness_attribute_type(attr_name)
{
Date => :date,
@@ -36,29 +25,39 @@ module ValidatesTimeliness
DateTime => :datetime
}[fields[attr_name.to_s].type] || :datetime
end
protected
def timeliness_type_cast_code(attr_name, var_name)
type = timeliness_attribute_type(attr_name)
"#{var_name} = Timeliness::Parser.parse(value, :#{type})"
end
end
module Reload
def reload(*args)
_clear_timeliness_cache
super
end
end
end
end
end
module Mongoid::Document
# Due to how Mongoid misuses ActiveSupport::Concern,
# the only way to override a core component method is
# using an append_features hook.
#
module TimelinessConcern
def append_features(base)
super
base.send :include, ValidatesTimeliness::AttributeMethods
base.send :include, ValidatesTimeliness::ORM::Mongoid
end
end
extend TimelinessConcern
include ValidatesTimeliness::AttributeMethods
include ValidatesTimeliness::ORM::Mongoid
# Pre-2.3 reload
if (instance_methods & ['reload', :reload]).present?
def reload_with_timeliness
_clear_timeliness_cache
reload_without_timeliness
end
alias_method_chain :reload, :timeliness
else
include ValidatesTimeliness::ORM::Mongoid::Reload
end
end

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._timeliness_raw_value_for(attr_name)
end
record.respond_to?(:_timeliness_raw_value_for) &&
record._timeliness_raw_value_for(attr_name.to_s)
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.10'
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 ]
@@ -47,9 +49,7 @@ class Person
attribute :birth_date, :date
attribute :birth_time, :time
attribute :birth_datetime, :datetime
validates_date :birth_date
validates_time :birth_time
validates_datetime :birth_datetime
define_attribute_methods model_attributes.keys
end
@@ -71,21 +71,31 @@ ActiveRecord::Schema.define(:version => 1) do
end
class Employee < ActiveRecord::Base
validates_date :birth_date
validates_time :birth_time
validates_datetime :birth_datetime
define_attribute_methods
attr_accessor :redefined_birth_date_called
validates_date :birth_date, :allow_nil => true
validates_date :birth_time, :allow_nil => true
validates_date :birth_datetime, :allow_nil => true
def birth_date=(value)
self.redefined_birth_date_called = true
super
end
end
Rspec.configure do |c|
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 = []
Person._validators.clear
Employee.reset_callbacks(:validate)
Employee.timeliness_validated_attributes = []
Employee._validators.clear
reset_validation_setup_for(Person)
reset_validation_setup_for(PersonWithShim)
end
RSpec.configure do |c|
c.filter_run_excluding :active_record => lambda {|version|
!(::ActiveRecord::VERSION::STRING.to_s =~ /^#{version.to_s}/)
}
end
end

View File

@@ -0,0 +1,36 @@
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
def reset_validation_setup_for(model_class)
model_class.reset_callbacks(:validate)
model_class._validators.clear
model_class.timeliness_validated_attributes = [] if model_class.respond_to?(:timeliness_validated_attributes)
model_class.undefine_attribute_methods
# This is a hack to avoid a disabled super method error message after an undef
model_class.instance_variable_set(:@generated_attribute_methods, nil)
model_class.instance_variable_set(:@generated_timeliness_methods, nil)
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

@@ -31,7 +31,7 @@ module TestModel
end
def initialize(attributes = nil)
@attributes = self.class.model_attributes.inject({}) do |hash, column|
@attributes = self.class.model_attributes.keys.inject({}) do |hash, column|
hash[column.to_s] = nil
hash
end
@@ -39,7 +39,7 @@ module TestModel
end
def attributes
@attributes.keys
@attributes
end
def attributes=(new_attributes={})
@@ -49,14 +49,12 @@ module TestModel
end
def method_missing(method_id, *args, &block)
if !self.class.attribute_methods_generated?
self.class.define_attribute_methods self.class.model_attributes.keys.map(&:to_s)
method_name = method_id.to_s
if match_attribute_method?(method_id.to_s)
self.class.define_attribute_methods self.class.model_attributes.keys
send(method_id, *args, &block)
else
super
end
end
end

View File

@@ -31,10 +31,33 @@ describe ValidatesTimeliness::AttributeMethods do
it 'should cache attribute raw value' do
r = PersonWithCache.new
r.birth_datetime = date_string = '2010-01-01'
r._timeliness_raw_value_for(:birth_datetime).should == date_string
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
it 'should be undefined if model class has dynamic attribute methods reset' do
# Force method definitions
PersonWithShim.validates_date :birth_date
r = PersonWithShim.new
r.birth_date = Time.now
write_method = RUBY_VERSION < '1.9' ? 'birth_date=' : :birth_date=
PersonWithShim.send(:generated_timeliness_methods).instance_methods.should include(write_method)
PersonWithShim.undefine_attribute_methods
PersonWithShim.send(:generated_timeliness_methods).instance_methods.should_not include(write_method)
end
context "with plugin parser" do
with_config(:use_plugin_parser, true)
class PersonWithParser
include TestModel
include TestModelShim
@@ -46,25 +69,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
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
after do
ValidatesTimeliness.dummy_date_for_time_type = @original_dummy_date
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,128 +13,105 @@ describe ValidatesTimeliness::Extensions::DateTimeSelect do
describe "datetime_select" do
it "should use param values when attribute is nil" do
params["person"] = {
"birth_datetime(1i)" => 2009,
"birth_datetime(2i)" => 2,
"birth_datetime(3i)" => 29,
"birth_datetime(4i)" => 12,
"birth_datetime(5i)" => 13,
"birth_datetime(6i)" => 14,
@params["person"] = {
"birth_datetime(1i)" => '2009',
"birth_datetime(2i)" => '2',
"birth_datetime(3i)" => '29',
"birth_datetime(4i)" => '12',
"birth_datetime(5i)" => '13',
"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"] = {
"birth_datetime(1i)" => 2009,
"birth_datetime(2i)" => 2,
"birth_datetime(3i)" => 29,
"birth_datetime(4i)" => 12,
"birth_datetime(5i)" => 13,
"birth_datetime(6i)" => 14,
@params["person"] = {
"birth_datetime(1i)" => '2009',
"birth_datetime(2i)" => '2',
"birth_datetime(3i)" => '29',
"birth_datetime(4i)" => '12',
"birth_datetime(5i)" => '13',
"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"] = {
"birth_date(1i)" => 2009,
"birth_date(2i)" => 2,
"birth_date(3i)" => 29,
@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)
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"] = {
"birth_date(1i)" => 2009,
"birth_date(2i)" => 2,
"birth_date(3i)" => 29,
@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)
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)
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)
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)
should_not_have_datetime_selected(:birth_time, :year, :month, :day)
end
it "should allow the day part to be discarded" do
@params["person"] = {
"birth_date(1i)" => '2009',
"birth_date(2i)" => '2',
}
@output = date_select(:person, :birth_date, :include_blank => true, :discard_day => true)
should_have_datetime_selected(:birth_date, :year => 2009, :month => 'February')
should_not_have_datetime_selected(:birth_time, :day)
@output.should have_tag("input[id=person_birth_date_3i][type=hidden][value='1']")
end
end
@@ -146,39 +121,43 @@ describe ValidatesTimeliness::Extensions::DateTimeSelect do
end
it "should use param values when attribute is nil" do
params["person"] = {
"birth_time(1i)" => 2000,
"birth_time(2i)" => 1,
"birth_time(3i)" => 1,
"birth_time(4i)" => 12,
"birth_time(5i)" => 13,
"birth_time(6i)" => 14,
@params["person"] = {
"birth_time(1i)" => '2000',
"birth_time(2i)" => '1',
"birth_time(3i)" => '1',
"birth_time(4i)" => '12',
"birth_time(5i)" => '13',
"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

@@ -1,21 +1,44 @@
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 assign a string value for invalid date portion' do
employee = record_with_multiparameter_attribute(:birth_datetime, [2000, 2, 31, 12, 0, 0])
employee.birth_datetime_before_type_cast.should eq '2000-02-31 12:00:00'
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'
it 'should assign a Time value for valid datetimes' do
employee = record_with_multiparameter_attribute(:birth_datetime, [2000, 2, 28, 12, 0, 0])
employee.birth_datetime_before_type_cast.should eq Time.local(2000, 2, 28, 12, 0, 0)
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)
it 'should assign a string value for incomplete time' do
employee = record_with_multiparameter_attribute(:birth_datetime, [2000, nil, nil])
employee.birth_datetime_before_type_cast.should eq '2000-00-00'
end
end
def instantiate_time_object(name, values)
employee.send(:instantiate_time_object, name, values)
context "date column" do
it 'should assign a string value for invalid date' do
employee = record_with_multiparameter_attribute(:birth_date, [2000, 2, 31])
employee.birth_date_before_type_cast.should eq '2000-02-31'
end
it 'should assign a Date value for valid date' do
employee = record_with_multiparameter_attribute(:birth_date, [2000, 2, 28])
employee.birth_date_before_type_cast.should eq Date.new(2000, 2, 28)
end
it 'should assign a string value for incomplete date' do
employee = record_with_multiparameter_attribute(:birth_date, [2000, nil, nil])
employee.birth_date_before_type_cast.should eq '2000-00-00'
end
end
def record_with_multiparameter_attribute(name, values)
hash = {}
values.each_with_index {|value, index| hash["#{name}(#{index+1}i)"] = value.to_s }
Employee.new(hash)
end
end

View File

@@ -13,9 +13,18 @@ describe ValidatesTimeliness, 'HelperMethods' do
Person.new.should respond_to(:validates_datetime)
end
it 'should validate instance when validation method called' do
it 'should validate instance using class validation defined' do
Person.validates_date :birth_date
r = Person.new
r.valid?
r.errors[:birth_date].should_not be_empty
end
it 'should validate instance using instance valiation method' do
r = Person.new
r.validates_date :birth_date
r.errors[:birth_date].should_not be_empty
end
end

View File

@@ -14,6 +14,30 @@ describe ValidatesTimeliness, 'ActiveRecord' do
Employee.new.should respond_to(:validates_time)
Employee.new.should respond_to(:validates_datetime)
end
it "should validate a valid value string" do
r = Employee.new
r.birth_date = '2012-01-01'
r.valid?
r.errors[:birth_date].should be_empty
end
it "should validate a invalid value string" do
r = Employee.new
r.birth_date = 'not a date'
r.valid?
r.errors[:birth_date].should_not be_empty
end
it "should validate a nil value" do
r = Employee.new
r.birth_date = nil
r.valid?
r.errors[:birth_date].should be_empty
end
end
it 'should determine type for attribute' do
@@ -23,24 +47,35 @@ describe ValidatesTimeliness, 'ActiveRecord' do
context "attribute write method" do
class EmployeeWithCache < ActiveRecord::Base
set_table_name 'employees'
validates_datetime :birth_datetime
validates_date :birth_date, :allow_blank => true
validates_datetime :birth_datetime, :allow_blank => true
end
it 'should cache attribute raw value' do
context 'value cache' do
context 'for datetime column' do
it 'should store raw value' do
r = EmployeeWithCache.new
r.birth_datetime = date_string = '2010-01-01'
r._timeliness_raw_value_for(:birth_datetime).should == date_string
r._timeliness_raw_value_for('birth_datetime').should == date_string
end
end
context 'for date column' do
it 'should store raw value' do
r = EmployeeWithCache.new
r.birth_date = date_string = '2010-01-01'
r._timeliness_raw_value_for('birth_date').should == date_string
end
end
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
validates_date :birth_date, :allow_blank => true
validates_datetime :birth_datetime, :allow_blank => true
end
it 'should parse a string value' do
@@ -49,25 +84,50 @@ describe ValidatesTimeliness, 'ActiveRecord' do
r.birth_date = '2010-01-01'
end
it 'should parse a invalid string value as nil' do
Timeliness::Parser.should_receive(:parse)
r = EmployeeWithParser.new
r.birth_date = 'not a date'
end
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
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 == 10.hours
end
after :all do
Time.zone = 'Australia/Melbourne'
ValidatesTimeliness.use_plugin_parser = false
r.birth_datetime.utc_offset.should == Time.zone.utc_offset
end
end
end
end
context "cached value" do
it 'should be cleared on reload' do
context "reload" do
it 'should clear cache value' do
r = Employee.create!
r.birth_date = '2010-01-01'
r.reload
r._timeliness_raw_value_for(:birth_date).should be_nil
r._timeliness_raw_value_for('birth_date').should be_nil
end
end
@@ -79,7 +139,34 @@ describe ValidatesTimeliness, 'ActiveRecord' do
it 'should return original value' do
r = Employee.new
r.birth_datetime = date_string = '2010-01-01'
r.birth_datetime_before_type_cast.should == date_string
end
it 'should return attribute if no attribute assignment has been made' do
datetime = Time.zone.local(2010,01,01)
Employee.create(:birth_datetime => datetime)
r = Employee.last
r.birth_datetime_before_type_cast.should match(/2010-01-01 00:00:00/)
end
context "with plugin parser" do
with_config(:use_plugin_parser, true)
it 'should return original value' do
r = Employee.new
r.birth_datetime = date_string = '2010-01-31'
r.birth_datetime_before_type_cast.should == date_string
end
end
end
context "define_attribute_methods" do
it "returns a falsy value if the attribute methods have already been generated" do
Employee.define_attribute_methods.should be_false
end
end
end

View File

@@ -12,20 +12,20 @@ Mongoid.configure do |config|
config.persist_in_safe_mode = false
end
describe ValidatesTimeliness, 'Mongoid' do
class Article
::ValidatesTimeliness.use_plugin_parser = true
include Mongoid::Document
ValidatesTimeliness.use_plugin_parser = true
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
ValidatesTimeliness.use_plugin_parser = false
end
describe ValidatesTimeliness, 'Mongoid' do
context "validation methods" do
it 'should be defined on the class' do
Article.should respond_to(:validates_date)
@@ -38,6 +38,30 @@ describe ValidatesTimeliness, 'Mongoid' do
Article.new.should respond_to(:validates_time)
Article.new.should respond_to(:validates_datetime)
end
it "should validate a valid value string" do
r = Article.new
r.publish_date = '2012-01-01'
r.valid?
r.errors[:publish_date].should be_empty
end
it "should validate a invalid value string" do
r = Article.new
r.publish_date = 'not a date'
r.valid?
r.errors[:publish_date].should_not be_empty
end
it "should validate a nil value" do
r = Article.new
r.publish_date = nil
r.valid?
r.errors[:publish_date].should be_empty
end
end
it 'should determine type for attribute' do
@@ -48,13 +72,11 @@ describe ValidatesTimeliness, 'Mongoid' do
it 'should cache attribute raw value' do
r = Article.new
r.publish_datetime = date_string = '2010-01-01'
r._timeliness_raw_value_for(:publish_datetime).should == date_string
r._timeliness_raw_value_for('publish_datetime').should == date_string
end
context "with plugin parser" do
before :all do
ValidatesTimeliness.use_plugin_parser = true
end
with_config(:use_plugin_parser, true)
it 'should parse a string value' do
Timeliness::Parser.should_receive(:parse)
@@ -62,14 +84,32 @@ describe ValidatesTimeliness, 'Mongoid' do
r.publish_date = '2010-01-01'
end
it 'should parse string into Time value' do
it 'should parse an invalid value as nil' do
Timeliness::Parser.should_receive(:parse)
r = Article.new
r.publish_datetime = '2010-01-01 12:00'
r.publish_datetime.should == Time.utc(2010,1,1,12,0)
r.publish_date = 'bad value'
r.publish_date.should be_nil
end
after :all do
ValidatesTimeliness.use_plugin_parser = false
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
context "for a datetime column" do
it 'should parse string into DateTime value' do
r = Article.new
r.publish_datetime = '2010-01-01 12:00'
r.publish_datetime.should be_kind_of(DateTime)
r.publish_datetime.should == DateTime.new(2010,1,1,12,0)
end
end
end
end
@@ -79,19 +119,19 @@ describe ValidatesTimeliness, 'Mongoid' do
r = Article.create!
r.publish_date = '2010-01-01'
r.reload
r._timeliness_raw_value_for(:publish_date).should be_nil
r._timeliness_raw_value_for('publish_date').should be_nil
end
end
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
rescue LoadError
puts "Mongoid specs skipped. Mongoid not installed"
rescue StandardError
puts "Mongoid specs skipped. MongoDB connection failed."
rescue StandardError => e
puts "Mongoid specs skipped. MongoDB connection failed with error: #{e.message}"
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
@@ -51,6 +46,17 @@ describe ValidatesTimeliness::Validator do
Person.validates_date :birth_date, :allow_nil => true
valid!(:birth_date, NIL)
end
context "with raw value cache" do
it "should not be valid with an invalid format" do
PersonWithShim.validates_date :birth_date, :allow_nil => true
p = PersonWithShim.new
p.birth_date = 'bogus'
p.should_not be_valid
end
end
end
describe ":allow_blank option" do
@@ -64,24 +70,43 @@ describe ValidatesTimeliness::Validator do
Person.validates_date :birth_date, :allow_blank => true
valid!(:birth_date, '')
end
context "with raw value cache" do
it "should not be valid with an invalid format" do
PersonWithShim.validates_date :birth_date, :allow_blank => true
p = PersonWithShim.new
p.birth_date = 'bogus'
p.should_not be_valid
end
end
end
describe ":between option" 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 +135,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 +148,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
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")
person.errors[:birth_date].first.should match("Error occurred validating birth_date")
end
end
it "should not be added when ignore_restriction_errors is true" do
ValidatesTimeliness.ignore_restriction_errors = true
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.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.name = "validates_timeliness"
s.version = ValidatesTimeliness::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.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}
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}
if s.respond_to? :specification_version then
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 3
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"]
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.5"])
end