Compare commits

...

16 Commits

Author SHA1 Message Date
Adam Meehan
a1dfbf5d7d v3.0.14 2012-08-23 18:40:47 +10:00
Adam Meehan
02fbdc6028 Fix for validates :timeliness form to add attributes to plugin set 2012-08-23 18:38:33 +10:00
Adam Meehan
4fe22458d3 Add mongoid appraisals 2012-08-23 18:37:38 +10:00
Adam Meehan
8c698be4c4 v3.0.13 2012-08-21 10:56:46 +10:00
Adam Meehan
091e7ecfa0 Tweak AR specs 2012-08-21 10:53:54 +10:00
Adam Meehan
8168bcbd3a Ignore more lock files 2012-08-19 22:59:40 +10:00
Adam Meehan
973bbfa82c Moving back to plugin cache for ActiveRecord
This simplifies the code a lot and fixes the issues with date and time
colummns when using the plugin parser.

Add appraisals for all rails 3 versions
2012-08-19 22:57:19 +10:00
Adam Meehan
62557e7e04 Allow any validated attribute to pass timezone aware check in AR 2012-08-09 12:53:29 +10:00
Adam Meehan
fd73c4eccd README touch ups 2012-08-09 11:55:53 +10:00
Adam Meehan
7bcdea1738 RSpec config cleanup 2012-07-13 21:43:29 +10:00
Adam Meehan
8898b8686c v3.0.12 2012-06-23 19:06:38 +10:00
Adam Meehan
aad2db8662 Remove unused cargo culted generator method 2012-06-23 18:58:33 +10:00
Adam Meehan
8e08cbf6e4 Fix load order issue for AR extension using Railite 2012-06-23 18:58:01 +10:00
Adam Meehan
8dd607975b v3.0.11 2012-04-01 16:48:53 +10:00
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
27 changed files with 477 additions and 139 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@ pkg/
.bundle/ .bundle/
.rvmrc .rvmrc
Gemfile.lock Gemfile.lock
gemfiles/*.lock

27
Appraisals Normal file
View File

@@ -0,0 +1,27 @@
appraise "rails_3_0" do
gem "rails", "~> 3.0.0"
end
appraise "rails_3_1" do
gem "rails", "~> 3.1.0"
end
appraise "rails_3_2" do
gem "rails", "~> 3.2.0"
end
appraise "mongoid_2_1" do
gem "mongoid", "~> 2.1.0"
end
appraise "mongoid_2_2" do
gem "mongoid", "~> 2.2.0"
end
appraise "mongoid_2_3" do
gem "mongoid", "~> 2.3.0"
end
appraise "mongoid_2_4" do
gem "mongoid", "~> 2.4.0"
end

View File

@@ -1,3 +1,19 @@
= 3.0.14 [2012-08-23]
* Fix for using validates :timeliness => {} form to correctly add attributes to timeliness validated attributes.
= 3.0.13 [2012-08-21]
* Fix ActiveRecord issues with using plugin parser by using old way of caching values.
* Allow any ActiveRecord non-column attribute to be validated
= 3.0.12 [2012-06-23]
* Fix load order issue when relying on Railtie to load ActiveRecord extension
= 3.0.11 [2012-04-01]
* Change dependency on Timeliness version due to a broken release
= 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] = 3.0.9 [2012-03-26]
* ActiveRecord 3.1+ suport * ActiveRecord 3.1+ suport
* Fixes for multiparameter extension with empty date values (thanks @mogox, @Sharagoz) * Fixes for multiparameter extension with empty date values (thanks @mogox, @Sharagoz)

View File

@@ -2,13 +2,15 @@ source 'http://rubygems.org'
gemspec gemspec
gem 'rails', '~> 3.2.1' gem 'rails', '~> 3.2.6'
gem 'rspec', '~> 2.8' gem 'rspec', '~> 2.8'
gem 'rspec-rails', '~> 2.8' gem 'rspec-rails', '~> 2.8'
gem 'timecop' gem 'timecop'
gem 'rspec_tag_matchers' gem 'rspec_tag_matchers'
gem 'ruby-debug', :platforms => [:ruby_18, :jruby] gem 'ruby-debug', :platforms => [:ruby_18, :jruby]
gem 'ruby-debug19', :platforms => [:ruby_19] gem 'debugger', :platforms => [:ruby_19]
gem 'appraisal'
gem 'sqlite3'
group :mongoid do group :mongoid do
gem 'mongoid', '~> 2.3.0' gem 'mongoid', '~> 2.3.0'

View File

@@ -1,7 +1,7 @@
= ValidatesTimeliness = ValidatesTimeliness
* Source: http://github.com/adzap/validates_timeliness * Source: http://github.com/adzap/validates_timeliness
* Bugs: http://github.com/adzap/validates_timeliness/issues * Issues: http://github.com/adzap/validates_timeliness/issues
== Description == Description
@@ -18,24 +18,19 @@ 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) * Only Rails date/time validation plugin offering complete validation (See ORM/ODM support)
* Adds extensions to fix Rails date/time select issues (See Extensions)
* Uses extensible date/time parser (Using {timeliness gem}[http://github.com/adzap/timeliness]. See Plugin Parser) * Uses extensible date/time parser (Using {timeliness gem}[http://github.com/adzap/timeliness]. See Plugin Parser)
* Adds extensions to fix Rails date/time select issues (See Extensions)
* Supports I18n for the error messages * Supports I18n for the error messages
* Supports Ruby 1.8.x, 1.9.x and Rubinius. * Supports all the Rubies (that any sane person would be using in production).
== Installation == Installation
As plugin (from master)
rails plugin install git://github.com/adzap/validates_timeliness.git
As gem
# in Gemfile # in Gemfile
gem 'validates_timeliness', '~> 3.0.2' gem 'validates_timeliness', '~> 3.0'
# Run bundler # Run bundler
$ bundle install $ bundle install
@@ -55,7 +50,7 @@ NOTE: You may wish to enable the plugin parser and the extensions to start. Plea
validates_datetime :occurred_at 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" :before_message => "must be at least 18 years old"
validates_datetime :finish_time, :after => :start_time # Method symbol validates_datetime :finish_time, :after => :start_time # Method symbol
@@ -79,7 +74,7 @@ validation method
validates :date_of_birth, :timeliness => {:on_or_before => lambda { Date.current }, :type => :date} validates :date_of_birth, :timeliness => {:on_or_before => lambda { Date.current }, :type => :date}
end end
# or even on a specific record, per ActiveModel API. or even on a specific record, per ActiveModel API.
@person.validates_date :date_of_birth, :on_or_before => lambda { Date.current } @person.validates_date :date_of_birth, :on_or_before => lambda { Date.current }
@@ -298,4 +293,4 @@ To see the generous people who have contributed code, take a look at the {contri
== License == License
Copyright (c) 2008-2010 Adam Meehan, released under the MIT license Copyright (c) 2008 Adam Meehan, released under the MIT license

View File

@@ -1,7 +1,9 @@
require 'bundler' require 'bundler'
Bundler::GemHelper.install_tasks require 'bundler/setup'
Bundler.setup require 'appraisal'
Bundler::GemHelper.install_tasks
require 'rake/rdoctask' require 'rake/rdoctask'
require 'rspec/core/rake_task' require 'rspec/core/rake_task'

View File

@@ -0,0 +1,16 @@
# This file was generated by Appraisal
source "http://rubygems.org"
gem "rails", "~> 3.2.6"
gem "rspec", "~> 2.8"
gem "rspec-rails", "~> 2.8"
gem "timecop"
gem "rspec_tag_matchers"
gem "ruby-debug", :platforms=>[:ruby_18, :jruby]
gem "debugger", :platforms=>[:ruby_19]
gem "appraisal"
gem "sqlite3"
gem "mongoid", "~> 2.1.0"
gemspec :path=>"../"

View File

@@ -0,0 +1,16 @@
# This file was generated by Appraisal
source "http://rubygems.org"
gem "rails", "~> 3.2.6"
gem "rspec", "~> 2.8"
gem "rspec-rails", "~> 2.8"
gem "timecop"
gem "rspec_tag_matchers"
gem "ruby-debug", :platforms=>[:ruby_18, :jruby]
gem "debugger", :platforms=>[:ruby_19]
gem "appraisal"
gem "sqlite3"
gem "mongoid", "~> 2.2.0"
gemspec :path=>"../"

View File

@@ -0,0 +1,16 @@
# This file was generated by Appraisal
source "http://rubygems.org"
gem "rails", "~> 3.2.6"
gem "rspec", "~> 2.8"
gem "rspec-rails", "~> 2.8"
gem "timecop"
gem "rspec_tag_matchers"
gem "ruby-debug", :platforms=>[:ruby_18, :jruby]
gem "debugger", :platforms=>[:ruby_19]
gem "appraisal"
gem "sqlite3"
gem "mongoid", "~> 2.3.0"
gemspec :path=>"../"

View File

@@ -0,0 +1,16 @@
# This file was generated by Appraisal
source "http://rubygems.org"
gem "rails", "~> 3.2.6"
gem "rspec", "~> 2.8"
gem "rspec-rails", "~> 2.8"
gem "timecop"
gem "rspec_tag_matchers"
gem "ruby-debug", :platforms=>[:ruby_18, :jruby]
gem "debugger", :platforms=>[:ruby_19]
gem "appraisal"
gem "sqlite3"
gem "mongoid", "~> 2.4.0"
gemspec :path=>"../"

View File

@@ -0,0 +1,15 @@
# This file was generated by Appraisal
source "http://rubygems.org"
gem "rspec", "~> 2.8"
gem "rspec-rails", "~> 2.8"
gem "timecop"
gem "rspec_tag_matchers"
gem "ruby-debug", :platforms=>[:ruby_18, :jruby]
gem "debugger", :platforms=>[:ruby_19]
gem "appraisal"
gem "sqlite3"
gem "rails", "~> 3.0.0"
gemspec :path=>"../"

View File

@@ -0,0 +1,15 @@
# This file was generated by Appraisal
source "http://rubygems.org"
gem "rspec", "~> 2.8"
gem "rspec-rails", "~> 2.8"
gem "timecop"
gem "rspec_tag_matchers"
gem "ruby-debug", :platforms=>[:ruby_18, :jruby]
gem "debugger", :platforms=>[:ruby_19]
gem "appraisal"
gem "sqlite3"
gem "rails", "~> 3.1.0"
gemspec :path=>"../"

View File

@@ -0,0 +1,15 @@
# This file was generated by Appraisal
source "http://rubygems.org"
gem "rspec", "~> 2.8"
gem "rspec-rails", "~> 2.8"
gem "timecop"
gem "rspec_tag_matchers"
gem "ruby-debug", :platforms=>[:ruby_18, :jruby]
gem "debugger", :platforms=>[:ruby_19]
gem "appraisal"
gem "sqlite3"
gem "rails", "~> 3.2.0"
gemspec :path=>"../"

View File

@@ -3,7 +3,6 @@ module ValidatesTimeliness
class InstallGenerator < Rails::Generators::Base class InstallGenerator < Rails::Generators::Base
desc "Copy ValidatesTimeliness default files" desc "Copy ValidatesTimeliness default files"
source_root File.expand_path('../templates', __FILE__) source_root File.expand_path('../templates', __FILE__)
class_option :template_engine
def copy_initializers def copy_initializers
copy_file 'validates_timeliness.rb', 'config/initializers/validates_timeliness.rb' copy_file 'validates_timeliness.rb', 'config/initializers/validates_timeliness.rb'

View File

@@ -58,6 +58,10 @@ module ValidatesTimeliness
# Setup method for plugin configuration # Setup method for plugin configuration
def self.setup def self.setup
yield self yield self
load_orms
end
def self.load_orms
extend_orms.each {|orm| require "validates_timeliness/orm/#{orm}" } extend_orms.each {|orm| require "validates_timeliness/orm/#{orm}" }
end end
end end

View File

@@ -82,7 +82,7 @@ module ValidatesTimeliness
end end
def _timeliness_raw_value_for(attr_name) def _timeliness_raw_value_for(attr_name)
@timeliness_cache && @timeliness_cache[attr_name.to_s] @timeliness_cache && @timeliness_cache[attr_name]
end end
def _clear_timeliness_cache def _clear_timeliness_cache

View File

@@ -15,12 +15,7 @@ module ActiveModel
end end
def timeliness_validation_for(attr_names, type) def timeliness_validation_for(attr_names, type)
options = _merge_attributes(attr_names).merge(:type => type) validates_with TimelinessValidator, _merge_attributes(attr_names).merge(:type => type)
if respond_to?(:timeliness_validated_attributes)
self.timeliness_validated_attributes ||= []
self.timeliness_validated_attributes += (attr_names - self.timeliness_validated_attributes)
end
validates_with TimelinessValidator, options
end end
end end

View File

@@ -3,61 +3,32 @@ module ValidatesTimeliness
module ActiveRecord module ActiveRecord
extend ActiveSupport::Concern extend ActiveSupport::Concern
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 module ClassMethods
public public
def timeliness_attribute_timezone_aware?(attr_name) def timeliness_attribute_timezone_aware?(attr_name)
attr_name = attr_name.to_s create_time_zone_conversion_attribute?(attr_name, timeliness_column_for_attribute(attr_name))
create_time_zone_conversion_attribute?(attr_name, columns_hash[attr_name])
end end
def timeliness_attribute_type(attr_name) def timeliness_attribute_type(attr_name)
columns_hash[attr_name.to_s].type timeliness_column_for_attribute(attr_name).type
end
def timeliness_column_for_attribute(attr_name)
columns_hash.fetch(attr_name.to_s) do |attr_name|
validation_type = _validators[attr_name.to_sym].find {|v| v.kind == :timeliness }.type
::ActiveRecord::ConnectionAdapters::Column.new(attr_name, nil, validation_type.to_s)
end
end end
def define_attribute_methods def define_attribute_methods
super.tap do |attribute_methods_generated| super.tap do |attribute_methods_generated|
use_before_type_cast = ValidatesTimeliness::ORM::ActiveRecord.use_plugin_cache? define_timeliness_methods true
define_timeliness_methods use_before_type_cast
end end
end end
protected 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) def timeliness_type_cast_code(attr_name, var_name)
type = timeliness_attribute_type(attr_name) type = timeliness_attribute_type(attr_name)
@@ -67,11 +38,9 @@ module ValidatesTimeliness
end end
end end
module Reload def reload(*args)
def reload(*args) _clear_timeliness_cache
_clear_timeliness_cache super
super
end
end end
end end

View File

@@ -21,7 +21,7 @@ module ValidatesTimeliness
def timeliness_attribute_type(attr_name) def timeliness_attribute_type(attr_name)
{ {
Date => :date, Date => :date,
Time => :datetime, Time => :time,
DateTime => :datetime DateTime => :datetime
}[fields[attr_name.to_s].type] || :datetime }[fields[attr_name.to_s].type] || :datetime
end end

View File

@@ -3,7 +3,8 @@ module ValidatesTimeliness
initializer "validates_timeliness.initialize_active_record", :after => 'active_record.initialize_timezone' do initializer "validates_timeliness.initialize_active_record", :after => 'active_record.initialize_timezone' do
ActiveSupport.on_load(:active_record) do ActiveSupport.on_load(:active_record) do
ValidatesTimeliness.default_timezone = ActiveRecord::Base.default_timezone ValidatesTimeliness.default_timezone = ActiveRecord::Base.default_timezone
ValidatesTimeliness.extend_orms = [ :active_record ] ValidatesTimeliness.extend_orms << :active_record
ValidatesTimeliness.load_orms
end end
end end

View File

@@ -22,6 +22,10 @@ module ValidatesTimeliness
RESTRICTION_ERROR_MESSAGE = "Error occurred validating %s for %s restriction:\n%s" RESTRICTION_ERROR_MESSAGE = "Error occurred validating %s for %s restriction:\n%s"
def self.kind
:timeliness
end
def initialize(options) def initialize(options)
@type = options.delete(:type) || :datetime @type = options.delete(:type) || :datetime
@allow_nil, @allow_blank = options.delete(:allow_nil), options.delete(:allow_blank) @allow_nil, @allow_blank = options.delete(:allow_nil), options.delete(:allow_blank)
@@ -35,6 +39,13 @@ module ValidatesTimeliness
super super
end end
def setup(model)
if model.respond_to?(:timeliness_validated_attributes)
model.timeliness_validated_attributes ||= []
model.timeliness_validated_attributes |= @attributes
end
end
def validate_each(record, attr_name, value) def validate_each(record, attr_name, value)
raw_value = attribute_raw_value(record, attr_name) || value raw_value = attribute_raw_value(record, attr_name) || value
return if (@allow_nil && raw_value.nil?) || (@allow_blank && raw_value.blank?) return if (@allow_nil && raw_value.nil?) || (@allow_blank && raw_value.blank?)
@@ -77,7 +88,7 @@ module ValidatesTimeliness
def attribute_raw_value(record, attr_name) def attribute_raw_value(record, attr_name)
record.respond_to?(:_timeliness_raw_value_for) && record.respond_to?(:_timeliness_raw_value_for) &&
record._timeliness_raw_value_for(attr_name) record._timeliness_raw_value_for(attr_name.to_s)
end end
def timezone_aware?(record, attr_name) def timezone_aware?(record, attr_name)

View File

@@ -1,3 +1,3 @@
module ValidatesTimeliness module ValidatesTimeliness
VERSION = '3.0.9' VERSION = '3.0.14'
end end

View File

@@ -92,10 +92,7 @@ RSpec.configure do |c|
reset_validation_setup_for(PersonWithShim) reset_validation_setup_for(PersonWithShim)
end end
RSpec.configure do |c| c.filter_run_excluding :active_record => lambda {|version|
c.filter_run_excluding :active_record => lambda {|version| !(::ActiveRecord::VERSION::STRING.to_s =~ /^#{version.to_s}/)
!(::ActiveRecord::VERSION::STRING.to_s =~ /^#{version.to_s}/) }
}
end
end end

View File

@@ -14,52 +14,177 @@ describe ValidatesTimeliness, 'ActiveRecord' do
Employee.new.should respond_to(:validates_time) Employee.new.should respond_to(:validates_time)
Employee.new.should respond_to(:validates_datetime) Employee.new.should respond_to(:validates_datetime)
end 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 end
it 'should determine type for attribute' do it 'should determine type for attribute' do
Employee.timeliness_attribute_type(:birth_date).should == :date Employee.timeliness_attribute_type(:birth_date).should eq :date
end
context 'attribute timezone awareness' do
let(:klass) {
Class.new(ActiveRecord::Base) do
self.table_name = 'employees'
attr_accessor :some_date
attr_accessor :some_time
attr_accessor :some_datetime
validates_date :some_date
validates_time :some_time
validates_datetime :some_datetime
end
}
context 'for column attribute' do
it 'should be detected from column type' do
klass.timeliness_attribute_timezone_aware?(:birth_date).should be_false
klass.timeliness_attribute_timezone_aware?(:birth_time).should be_false
klass.timeliness_attribute_timezone_aware?(:birth_datetime).should be_true
end
end
context 'for non-column attribute' do
it 'should be detected from the validation type' do
klass.timeliness_attribute_timezone_aware?(:some_date).should be_false
klass.timeliness_attribute_timezone_aware?(:some_time).should be_false
klass.timeliness_attribute_timezone_aware?(:some_datetime).should be_true
end
end
end end
context "attribute write method" do context "attribute write method" do
class EmployeeWithCache < ActiveRecord::Base class EmployeeWithCache < ActiveRecord::Base
set_table_name 'employees' self.table_name = 'employees'
validates_datetime :birth_datetime validates_date :birth_date, :allow_blank => true
validates_time :birth_time, :allow_blank => true
validates_datetime :birth_datetime, :allow_blank => true
end end
it 'should cache attribute raw value' do context 'value cache' do
r = EmployeeWithCache.new context 'for datetime column' do
r.birth_datetime = date_string = '2010-01-01' it 'should store raw value' do
r._timeliness_raw_value_for('birth_datetime').should == date_string r = EmployeeWithCache.new
r.birth_datetime = datetime_string = '2010-01-01 12:30'
r._timeliness_raw_value_for('birth_datetime').should eq datetime_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 eq date_string
end
end
context 'for time column' do
it 'should store raw value' do
r = EmployeeWithCache.new
r.birth_time = time_string = '12:12'
r._timeliness_raw_value_for('birth_time').should eq time_string
end
end
end end
context "with plugin parser" do context "with plugin parser" do
with_config(:use_plugin_parser, true) with_config(:use_plugin_parser, true)
class EmployeeWithParser < ActiveRecord::Base class EmployeeWithParser < ActiveRecord::Base
set_table_name 'employees' self.table_name = 'employees'
validates_date :birth_date validates_date :birth_date, :allow_blank => true
validates_datetime :birth_datetime validates_time :birth_time, :allow_blank => true
validates_datetime :birth_datetime, :allow_blank => true
end end
it 'should parse a string value' do context "for a date column" do
Timeliness::Parser.should_receive(:parse) it 'should parse a string value' do
r = EmployeeWithParser.new Timeliness::Parser.should_receive(:parse)
r.birth_date = '2010-01-01'
end
context "for a date column", :active_record => '3.0' do r = EmployeeWithParser.new
it 'should store a date value after parsing string' 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 valid'
end
it 'should store a Date value after parsing string' do
r = EmployeeWithParser.new r = EmployeeWithParser.new
r.birth_date = '2010-01-01' r.birth_date = '2010-01-01'
r.birth_date.should be_kind_of(Date) r.birth_date.should be_kind_of(Date)
r.birth_date.should == Date.new(2010, 1, 1) r.birth_date.should eq Date.new(2010, 1, 1)
end
end
context "for a time column" do
it 'should parse a string value' do
Timeliness::Parser.should_receive(:parse)
r = EmployeeWithParser.new
r.birth_time = '12:30'
end
it 'should parse a invalid string value as nil' do
Timeliness::Parser.should_receive(:parse)
r = EmployeeWithParser.new
r.birth_time = 'not valid'
end
it 'should store a Time value after parsing string' do
r = EmployeeWithParser.new
r.birth_time = '12:30'
r.birth_time.should be_kind_of(Time)
r.birth_time.should eq Time.utc(2000, 1, 1, 12, 30)
end end
end end
context "for a datetime column" do context "for a datetime column" do
with_config(:default_timezone, 'Australia/Melbourne') with_config(:default_timezone, 'Australia/Melbourne')
it 'should parse a string value' do
Timeliness::Parser.should_receive(:parse)
r = EmployeeWithParser.new
r.birth_datetime = '2010-01-01 12:00'
end
it 'should parse a invalid string value as nil' do
Timeliness::Parser.should_receive(:parse)
r = EmployeeWithParser.new
r.birth_datetime = 'not valid'
end
it 'should parse string into Time value' do it 'should parse string into Time value' do
r = EmployeeWithParser.new r = EmployeeWithParser.new
r.birth_datetime = '2010-01-01 12:00' r.birth_datetime = '2010-01-01 12:00'
@@ -71,16 +196,17 @@ describe ValidatesTimeliness, 'ActiveRecord' do
r = EmployeeWithParser.new r = EmployeeWithParser.new
r.birth_datetime = '2010-06-01 12:00' r.birth_datetime = '2010-06-01 12:00'
r.birth_datetime.utc_offset.should == Time.zone.utc_offset r.birth_datetime.utc_offset.should eq Time.zone.utc_offset
end end
end end
end end
end end
context "cached value" do context "reload" do
it 'should be cleared on reload' do it 'should clear cache value' do
r = Employee.create! r = Employee.create!
r.birth_date = '2010-01-01' r.birth_date = '2010-01-01'
r.reload r.reload
r._timeliness_raw_value_for('birth_date').should be_nil r._timeliness_raw_value_for('birth_date').should be_nil
@@ -96,7 +222,7 @@ describe ValidatesTimeliness, 'ActiveRecord' do
r = Employee.new r = Employee.new
r.birth_datetime = date_string = '2010-01-01' r.birth_datetime = date_string = '2010-01-01'
r.birth_datetime_before_type_cast.should == date_string r.birth_datetime_before_type_cast.should eq date_string
end end
it 'should return attribute if no attribute assignment has been made' do it 'should return attribute if no attribute assignment has been made' do
@@ -114,7 +240,7 @@ describe ValidatesTimeliness, 'ActiveRecord' do
r = Employee.new r = Employee.new
r.birth_datetime = date_string = '2010-01-31' r.birth_datetime = date_string = '2010-01-31'
r.birth_datetime_before_type_cast.should == date_string r.birth_datetime_before_type_cast.should eq date_string
end end
end end

View File

@@ -5,6 +5,7 @@ begin
require 'mongoid' require 'mongoid'
require 'validates_timeliness/orm/mongoid' require 'validates_timeliness/orm/mongoid'
Mongoid.configure do |config| Mongoid.configure do |config|
name = "validates_timeliness_test" name = "validates_timeliness_test"
host = "localhost" host = "localhost"
@@ -16,17 +17,17 @@ describe ValidatesTimeliness, 'Mongoid' do
class Article class Article
include Mongoid::Document include Mongoid::Document
ValidatesTimeliness.use_plugin_parser = true
field :publish_date, :type => Date field :publish_date, :type => Date
field :publish_time, :type => Time field :publish_time, :type => Time
field :publish_datetime, :type => DateTime field :publish_datetime, :type => DateTime
validates_date :publish_date, :allow_nil => true validates_date :publish_date, :allow_nil => true
validates_time :publish_time, :allow_nil => true validates_time :publish_time, :allow_nil => true
validates_datetime :publish_datetime, :allow_nil => true validates_datetime :publish_datetime, :allow_nil => true
ValidatesTimeliness.use_plugin_parser = false
end end
context "validation methods" do context "validation methods" do
let(:record) { Article.new }
it 'should be defined on the class' do it 'should be defined on the class' do
Article.should respond_to(:validates_date) Article.should respond_to(:validates_date)
Article.should respond_to(:validates_time) Article.should respond_to(:validates_time)
@@ -34,9 +35,33 @@ describe ValidatesTimeliness, 'Mongoid' do
end end
it 'should be defined on the instance' do it 'should be defined on the instance' do
Article.new.should respond_to(:validates_date) record.should respond_to(:validates_date)
Article.new.should respond_to(:validates_time) record.should respond_to(:validates_time)
Article.new.should respond_to(:validates_datetime) record.should respond_to(:validates_datetime)
end
it "should validate a valid value string" do
record.publish_date = '2012-01-01'
record.valid?
record.errors[:publish_date].should be_empty
end
it "should validate a invalid value string" do
begin
record.publish_date = 'not a date'
rescue
end
record.valid?
record.errors[:publish_date].should_not be_empty
end
it "should validate a nil value" do
record.publish_date = nil
record.valid?
record.errors[:publish_date].should be_empty
end end
end end
@@ -45,46 +70,97 @@ describe ValidatesTimeliness, 'Mongoid' do
end end
context "attribute write method" do context "attribute write method" do
let(:record) { Article.new }
it 'should cache attribute raw value' do it 'should cache attribute raw value' do
r = Article.new record.publish_datetime = date_string = '2010-01-01'
r.publish_datetime = date_string = '2010-01-01'
r._timeliness_raw_value_for(:publish_datetime).should == date_string record._timeliness_raw_value_for('publish_datetime').should == date_string
end end
context "with plugin parser" do context "with plugin parser" do
with_config(:use_plugin_parser, true) let(:record) { ArticleWithParser.new }
it 'should parse a string value' do class ArticleWithParser
Timeliness::Parser.should_receive(:parse) include Mongoid::Document
r = Article.new field :publish_date, :type => Date
r.publish_date = '2010-01-01' field :publish_time, :type => Time
end field :publish_datetime, :type => DateTime
it 'should parse an invalid value as nil' do ValidatesTimeliness.use_plugin_parser = true
Timeliness::Parser.should_receive(:parse) validates_date :publish_date, :allow_nil => true
r = Article.new validates_time :publish_time, :allow_nil => true
r.publish_date = 'bad value' validates_datetime :publish_datetime, :allow_nil => true
ValidatesTimeliness.use_plugin_parser = false
r.publish_date.should be_nil
end end
context "for a date column" do context "for a date column" do
it 'should store a Date value after parsing string' do it 'should parse a string value' do
r = Article.new Timeliness::Parser.should_receive(:parse)
r.publish_date = '2010-01-01'
r.publish_date.should be_kind_of(Date) record.publish_date = '2010-01-01'
r.publish_date.should == Date.new(2010, 1, 1) end
it 'should parse a invalid string value as nil' do
Timeliness::Parser.should_receive(:parse)
record.publish_date = 'not valid'
end
it 'should store a Date value after parsing string' do
record.publish_date = '2010-01-01'
record.publish_date.should be_kind_of(Date)
record.publish_date.should eq Date.new(2010, 1, 1)
end
end
context "for a time column" do
it 'should parse a string value' do
Timeliness::Parser.should_receive(:parse)
record.publish_time = '12:30'
end
it 'should parse a invalid string value as nil' do
Timeliness::Parser.should_receive(:parse)
record.publish_time = 'not valid'
end
it 'should store a Time value after parsing string' do
record.publish_time = '12:30'
record.publish_time.should be_kind_of(Time)
record.publish_time.should eq Time.utc(2000, 1, 1, 12, 30)
end end
end end
context "for a datetime column" do context "for a datetime column" do
it 'should parse string into DateTime value' do with_config(:default_timezone, 'Australia/Melbourne')
r = Article.new
r.publish_datetime = '2010-01-01 12:00'
r.publish_datetime.should be_kind_of(DateTime) it 'should parse a string value' do
r.publish_datetime.should == DateTime.new(2010,1,1,12,0) Timeliness::Parser.should_receive(:parse)
record.publish_datetime = '2010-01-01 12:00'
end
it 'should parse a invalid string value as nil' do
Timeliness::Parser.should_receive(:parse)
record.publish_datetime = 'not valid'
end
it 'should parse string into DateTime value' do
record.publish_datetime = '2010-01-01 12:00'
record.publish_datetime.should be_kind_of(DateTime)
end
pending 'should parse string as current timezone' do
record.publish_datetime = '2010-06-01 12:00'
record.publish_datetime.utc_offset.should eq Time.zone.utc_offset
end end
end end
end end
@@ -92,10 +168,10 @@ describe ValidatesTimeliness, 'Mongoid' do
context "cached value" do context "cached value" do
it 'should be cleared on reload' do it 'should be cleared on reload' do
r = Article.create! record = Article.create!
r.publish_date = '2010-01-01' record.publish_date = '2010-01-01'
r.reload record.reload
r._timeliness_raw_value_for(:publish_date).should be_nil record._timeliness_raw_value_for('publish_date').should be_nil
end end
end end

View File

@@ -19,6 +19,14 @@ describe ValidatesTimeliness::Validator do
Person.validates :birth_datetime, :timeliness => {:is_at => Time.mktime(2010,1,1)} Person.validates :birth_datetime, :timeliness => {:is_at => Time.mktime(2010,1,1)}
Person.validators.first.type.should == :datetime Person.validators.first.type.should == :datetime
end end
it 'should add attribute to timeliness attributes set' do
PersonWithShim.timeliness_validated_attributes.should_not include(:birth_time)
PersonWithShim.validates :birth_time, :timeliness => {:is_at => "12:30"}
PersonWithShim.timeliness_validated_attributes.should include(:birth_time)
end
end end
it 'should not be valid for value which not valid date or time value' do it 'should not be valid for value which not valid date or time value' do

View File

@@ -12,9 +12,9 @@ Gem::Specification.new do |s|
s.homepage = %q{http://github.com/adzap/validates_timeliness} s.homepage = %q{http://github.com/adzap/validates_timeliness}
s.require_paths = ["lib"] s.require_paths = ["lib"]
s.files = `git ls-files`.split("\n") - %w{ .gitignore .rspec Gemfile Gemfile.lock autotest/discover.rb } s.files = `git ls-files`.split("\n") - %w{ .gitignore .rspec Gemfile Gemfile.lock autotest/discover.rb Appraisals Travis.yml } - Dir['gemsfiles/*']
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.extra_rdoc_files = ["README.rdoc", "CHANGELOG.rdoc", "LICENSE"] s.extra_rdoc_files = ["README.rdoc", "CHANGELOG.rdoc", "LICENSE"]
s.add_runtime_dependency(%q<timeliness>, ["~> 0.3.4"]) s.add_runtime_dependency(%q<timeliness>, ["~> 0.3.6"])
end end