validates_timeliness 3.0.15 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +21 -0
- data/CHANGELOG.rdoc +0 -5
- data/README.rdoc +5 -5
- data/gemfiles/rails_4_0.gemfile +19 -0
- data/gemfiles/rails_4_1.gemfile +19 -0
- data/gemfiles/rails_4_2.gemfile +19 -0
- data/lib/generators/validates_timeliness/templates/validates_timeliness.rb +2 -2
- data/lib/validates_timeliness.rb +1 -1
- data/lib/validates_timeliness/attribute_methods.rb +36 -36
- data/lib/validates_timeliness/extensions.rb +3 -4
- data/lib/validates_timeliness/extensions/date_time_select.rb +2 -9
- data/lib/validates_timeliness/extensions/multiparameter_handler.rb +59 -65
- data/lib/validates_timeliness/helper_methods.rb +8 -2
- data/lib/validates_timeliness/orm/active_record.rb +59 -13
- data/lib/validates_timeliness/validator.rb +13 -5
- data/lib/validates_timeliness/version.rb +1 -1
- data/spec/spec_helper.rb +3 -2
- data/spec/support/model_helpers.rb +4 -4
- data/spec/support/tag_matcher.rb +35 -0
- data/spec/support/test_model.rb +0 -1
- data/spec/validates_timeliness/attribute_methods_spec.rb +10 -10
- data/spec/validates_timeliness/conversion_spec.rb +41 -41
- data/spec/validates_timeliness/extensions/date_time_select_spec.rb +5 -4
- data/spec/validates_timeliness/extensions/multiparameter_handler_spec.rb +8 -7
- data/spec/validates_timeliness/helper_methods_spec.rb +8 -8
- data/spec/validates_timeliness/orm/active_record_spec.rb +37 -37
- data/spec/validates_timeliness/validator/after_spec.rb +3 -3
- data/spec/validates_timeliness/validator/before_spec.rb +3 -3
- data/spec/validates_timeliness/validator/is_at_spec.rb +4 -4
- data/spec/validates_timeliness/validator/on_or_after_spec.rb +3 -3
- data/spec/validates_timeliness/validator/on_or_before_spec.rb +3 -3
- data/spec/validates_timeliness/validator_spec.rb +26 -26
- data/spec/validates_timeliness_spec.rb +8 -8
- metadata +7 -11
- data/gemfiles/mongoid_2_1.gemfile +0 -16
- data/gemfiles/mongoid_2_2.gemfile +0 -16
- data/gemfiles/mongoid_2_3.gemfile +0 -16
- data/gemfiles/mongoid_2_4.gemfile +0 -16
- data/gemfiles/rails_3_0.gemfile +0 -15
- data/gemfiles/rails_3_1.gemfile +0 -15
- data/gemfiles/rails_3_2.gemfile +0 -15
- data/lib/validates_timeliness/orm/mongoid.rb +0 -49
- data/spec/validates_timeliness/orm/mongoid_spec.rb +0 -223
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c730e7683c67e1fce0a8a2e0b6dcba331b812e36
|
4
|
+
data.tar.gz: 904f0cfe44ca9d764e051d1d656cf34cbb6a5dba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd5326ac226351463fab7d317fadfb96bab6858b0231cfa1ee2b3fb49b974e6aeacf9cff498a22088132cd675d823054db6f0b622ea6db034d0884f0cdfab1e1
|
7
|
+
data.tar.gz: fe62be44d7d398c17d5762f91335e11187afdd8e2cb3f15e69de95feb8b764b03773f038c009ca72e299a793378ee680e8ea7ebcb62aaec341ef17b02fa1f747
|
data/.travis.yml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
language: ruby
|
2
|
+
cache: bundler
|
3
|
+
|
4
|
+
gemfile:
|
5
|
+
- gemfiles/rails_4_0.gemfile
|
6
|
+
- gemfiles/rails_4_1.gemfile
|
7
|
+
- gemfiles/rails_4_2.gemfile
|
8
|
+
|
9
|
+
rvm:
|
10
|
+
- "2.0.0"
|
11
|
+
- "2.2.0"
|
12
|
+
- "2.3.0"
|
13
|
+
|
14
|
+
script: 'bundle exec rake'
|
15
|
+
|
16
|
+
notifications:
|
17
|
+
email:
|
18
|
+
recipients:
|
19
|
+
- adam.meehan@gmail.com
|
20
|
+
on_failure: change
|
21
|
+
on_success: never
|
data/CHANGELOG.rdoc
CHANGED
@@ -1,8 +1,3 @@
|
|
1
|
-
= 3.0.15 [2015-12-29]
|
2
|
-
* Fixes mongoid 3 support and removes mongoid 2 support(johnnyshields)
|
3
|
-
* Some documentation/comments tidying
|
4
|
-
* Some general tidying up
|
5
|
-
|
6
1
|
= 3.0.14 [2012-08-23]
|
7
2
|
* Fix for using validates :timeliness => {} form to correctly add attributes to timeliness validated attributes.
|
8
3
|
|
data/README.rdoc
CHANGED
@@ -5,9 +5,9 @@
|
|
5
5
|
|
6
6
|
== Description
|
7
7
|
|
8
|
-
Complete validation of dates, times and datetimes for Rails
|
8
|
+
Complete validation of dates, times and datetimes for Rails 4.x and ActiveModel.
|
9
9
|
|
10
|
-
If you a looking for the old version for Rails
|
10
|
+
If you a looking for the old version for Rails 3.x go here[http://github.com/adzap/validates_timeliness/tree/v3.x].
|
11
11
|
|
12
12
|
|
13
13
|
== Features
|
@@ -30,7 +30,7 @@ If you a looking for the old version for Rails 2.x go here[http://github.com/adz
|
|
30
30
|
== Installation
|
31
31
|
|
32
32
|
# in Gemfile
|
33
|
-
gem 'validates_timeliness', '~>
|
33
|
+
gem 'validates_timeliness', '~> 4.0'
|
34
34
|
|
35
35
|
# Run bundler
|
36
36
|
$ bundle install
|
@@ -137,8 +137,8 @@ like so
|
|
137
137
|
|
138
138
|
ValidatesTimeliness.setup do |config|
|
139
139
|
|
140
|
-
# Extend ORM/ODMs for full support (:active_record
|
141
|
-
config.extend_orms = [ :
|
140
|
+
# Extend ORM/ODMs for full support (:active_record).
|
141
|
+
config.extend_orms = [ :active_record ]
|
142
142
|
|
143
143
|
end
|
144
144
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "~> 4.0.0"
|
6
|
+
gem "rspec", "~> 3.0.0"
|
7
|
+
gem "rspec-rails", "~> 3.0.0"
|
8
|
+
gem "timecop"
|
9
|
+
gem "rspec_tag_matchers"
|
10
|
+
gem "byebug"
|
11
|
+
gem "appraisal"
|
12
|
+
gem "sqlite3"
|
13
|
+
gem "nokogiri", "1.6.7"
|
14
|
+
|
15
|
+
group :active_record do
|
16
|
+
gem "sqlite3-ruby", :require => "sqlite3"
|
17
|
+
end
|
18
|
+
|
19
|
+
gemspec :path => "../"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "~> 4.1.0"
|
6
|
+
gem "rspec", "~> 3.0.0"
|
7
|
+
gem "rspec-rails", "~> 3.0.0"
|
8
|
+
gem "timecop"
|
9
|
+
gem "rspec_tag_matchers"
|
10
|
+
gem "byebug"
|
11
|
+
gem "appraisal"
|
12
|
+
gem "sqlite3"
|
13
|
+
gem "nokogiri", "1.6.7"
|
14
|
+
|
15
|
+
group :active_record do
|
16
|
+
gem "sqlite3-ruby", :require => "sqlite3"
|
17
|
+
end
|
18
|
+
|
19
|
+
gemspec :path => "../"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "~> 4.2.0"
|
6
|
+
gem "rspec", "~> 3.0.0"
|
7
|
+
gem "rspec-rails", "~> 3.0.0"
|
8
|
+
gem "timecop"
|
9
|
+
gem "rspec_tag_matchers"
|
10
|
+
gem "byebug"
|
11
|
+
gem "appraisal"
|
12
|
+
gem "sqlite3"
|
13
|
+
gem "nokogiri", "1.6.7"
|
14
|
+
|
15
|
+
group :active_record do
|
16
|
+
gem "sqlite3-ruby", :require => "sqlite3"
|
17
|
+
end
|
18
|
+
|
19
|
+
gemspec :path => "../"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
ValidatesTimeliness.setup do |config|
|
2
|
-
# Extend ORM/ODMs for full support (:active_record
|
3
|
-
|
2
|
+
# Extend ORM/ODMs for full support (:active_record included).
|
3
|
+
config.extend_orms = [ :active_record ]
|
4
4
|
#
|
5
5
|
# Default timezone
|
6
6
|
# config.default_timezone = :utc
|
data/lib/validates_timeliness.rb
CHANGED
@@ -28,7 +28,7 @@ module ValidatesTimeliness
|
|
28
28
|
attr_accessor :extend_orms, :ignore_restriction_errors, :restriction_shorthand_symbols, :use_plugin_parser
|
29
29
|
end
|
30
30
|
|
31
|
-
# Extend ORM/ODMs for full support (:active_record
|
31
|
+
# Extend ORM/ODMs for full support (:active_record).
|
32
32
|
self.extend_orms = []
|
33
33
|
|
34
34
|
# Ignore errors when restriction options are evaluated
|
@@ -20,13 +20,6 @@ module ValidatesTimeliness
|
|
20
20
|
:datetime
|
21
21
|
end
|
22
22
|
|
23
|
-
def undefine_attribute_methods
|
24
|
-
super
|
25
|
-
undefine_timeliness_attribute_methods
|
26
|
-
end
|
27
|
-
|
28
|
-
protected
|
29
|
-
|
30
23
|
def define_timeliness_methods(before_type_cast=false)
|
31
24
|
return if timeliness_validated_attributes.blank?
|
32
25
|
timeliness_validated_attributes.each do |attr_name|
|
@@ -34,55 +27,62 @@ module ValidatesTimeliness
|
|
34
27
|
end
|
35
28
|
end
|
36
29
|
|
30
|
+
def generated_timeliness_methods
|
31
|
+
@generated_timeliness_methods ||= Module.new { |m|
|
32
|
+
extend Mutex_m
|
33
|
+
}.tap { |mod| include mod }
|
34
|
+
end
|
35
|
+
|
36
|
+
def undefine_attribute_methods
|
37
|
+
super.tap { undefine_timeliness_attribute_methods }
|
38
|
+
end
|
39
|
+
|
40
|
+
def undefine_timeliness_attribute_methods
|
41
|
+
generated_timeliness_methods.synchronize do
|
42
|
+
generated_timeliness_methods.module_eval do
|
43
|
+
instance_methods.each { |m| undef_method(m) }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
37
50
|
def define_attribute_timeliness_methods(attr_name, before_type_cast=false)
|
38
51
|
define_timeliness_write_method(attr_name)
|
39
52
|
define_timeliness_before_type_cast_method(attr_name) if before_type_cast
|
40
53
|
end
|
41
54
|
|
42
55
|
def define_timeliness_write_method(attr_name)
|
43
|
-
|
56
|
+
generated_timeliness_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
44
57
|
def #{attr_name}=(value)
|
45
|
-
|
46
|
-
@timeliness_cache ||= {}
|
47
|
-
@timeliness_cache["#{attr_name}"] = original_value
|
48
|
-
#{ "if value.is_a?(String)\n#{timeliness_type_cast_code(attr_name, 'value')}\nend" if ValidatesTimeliness.use_plugin_parser }
|
49
|
-
|
50
|
-
super(value)
|
58
|
+
write_timeliness_attribute('#{attr_name}', value)
|
51
59
|
end
|
52
|
-
|
53
|
-
generated_timeliness_methods.module_eval(method_body, __FILE__, line)
|
60
|
+
STR
|
54
61
|
end
|
55
62
|
|
56
63
|
def define_timeliness_before_type_cast_method(attr_name)
|
57
|
-
|
64
|
+
generated_timeliness_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
58
65
|
def #{attr_name}_before_type_cast
|
59
|
-
|
66
|
+
read_timeliness_attribute_before_type_cast('#{attr_name}')
|
60
67
|
end
|
61
|
-
|
62
|
-
generated_timeliness_methods.module_eval(method_body, __FILE__, line)
|
68
|
+
STR
|
63
69
|
end
|
70
|
+
end
|
64
71
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
timezone = :current if timezone_aware
|
69
|
-
|
70
|
-
"#{var_name} = Timeliness::Parser.parse(#{var_name}, :#{type}, :zone => #{timezone.inspect})"
|
71
|
-
end
|
72
|
+
def write_timeliness_attribute(attr_name, value)
|
73
|
+
@timeliness_cache ||= {}
|
74
|
+
@timeliness_cache[attr_name] = value
|
72
75
|
|
73
|
-
|
74
|
-
|
76
|
+
if ValidatesTimeliness.use_plugin_parser
|
77
|
+
timezone = :current if self.class.timeliness_attribute_timezone_aware?(attr_name)
|
78
|
+
value = Timeliness::Parser.parse(value, self.class.timeliness_attribute_type(attr_name), :zone => timezone)
|
75
79
|
end
|
76
80
|
|
77
|
-
|
78
|
-
generated_timeliness_methods.module_eval do
|
79
|
-
instance_methods.each { |m| undef_method(m) }
|
80
|
-
end
|
81
|
-
end
|
81
|
+
@attributes[attr_name] = value
|
82
82
|
end
|
83
83
|
|
84
|
-
def
|
85
|
-
@timeliness_cache && @timeliness_cache[attr_name]
|
84
|
+
def read_timeliness_attribute_before_type_cast(attr_name)
|
85
|
+
@timeliness_cache && @timeliness_cache[attr_name] || @attributes[attr_name]
|
86
86
|
end
|
87
87
|
|
88
88
|
def _clear_timeliness_cache
|
@@ -1,14 +1,13 @@
|
|
1
1
|
module ValidatesTimeliness
|
2
2
|
module Extensions
|
3
|
-
autoload :DateTimeSelect,
|
4
|
-
autoload :MultiparameterHandler, 'validates_timeliness/extensions/multiparameter_handler'
|
3
|
+
autoload :DateTimeSelect, 'validates_timeliness/extensions/date_time_select'
|
5
4
|
end
|
6
5
|
|
7
6
|
def self.enable_date_time_select_extension!
|
8
|
-
::ActionView::Helpers::
|
7
|
+
::ActionView::Helpers::Tags::DateSelect.send(:include, ValidatesTimeliness::Extensions::DateTimeSelect)
|
9
8
|
end
|
10
9
|
|
11
10
|
def self.enable_multiparameter_extension!
|
12
|
-
|
11
|
+
require 'validates_timeliness/extensions/multiparameter_handler'
|
13
12
|
end
|
14
13
|
end
|
@@ -9,7 +9,6 @@ module ValidatesTimeliness
|
|
9
9
|
# It's a minor usability improvement which is rarely an issue for the user.
|
10
10
|
|
11
11
|
included do
|
12
|
-
alias_method_chain :datetime_selector, :timeliness
|
13
12
|
alias_method_chain :value, :timeliness
|
14
13
|
end
|
15
14
|
|
@@ -33,15 +32,8 @@ module ValidatesTimeliness
|
|
33
32
|
end
|
34
33
|
end
|
35
34
|
|
36
|
-
def datetime_selector_with_timeliness(*args)
|
37
|
-
@timeliness_date_or_time_tag = true
|
38
|
-
datetime_selector_without_timeliness(*args)
|
39
|
-
end
|
40
|
-
|
41
35
|
def value_with_timeliness(object)
|
42
|
-
|
43
|
-
return value_without_timeliness(object)
|
44
|
-
end
|
36
|
+
return value_without_timeliness(object) unless @template_object.params[@object_name]
|
45
37
|
|
46
38
|
@template_object.params[@object_name]
|
47
39
|
|
@@ -56,6 +48,7 @@ module ValidatesTimeliness
|
|
56
48
|
|
57
49
|
TimelinessDateTime.new(*values)
|
58
50
|
end
|
51
|
+
|
59
52
|
end
|
60
53
|
end
|
61
54
|
end
|
@@ -1,80 +1,74 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module MultiparameterHandler
|
4
|
-
extend ActiveSupport::Concern
|
1
|
+
ActiveRecord::AttributeAssignment::MultiparameterAttribute.class_eval do
|
2
|
+
private
|
5
3
|
|
6
|
-
|
7
|
-
|
4
|
+
# Yield if date values are valid
|
5
|
+
def validate_multiparameter_date_values(set_values)
|
6
|
+
if set_values[0..2].all?{ |v| v.present? } && Date.valid_civil?(*set_values[0..2])
|
7
|
+
yield
|
8
|
+
else
|
9
|
+
invalid_multiparameter_date_or_time_as_string(set_values)
|
10
|
+
end
|
11
|
+
end
|
8
12
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
def invalid_multiparameter_date_or_time_as_string(values)
|
14
|
+
value = [values[0], *values[1..2].map {|s| s.to_s.rjust(2,"0")} ].join("-")
|
15
|
+
value += ' ' + values[3..5].map {|s| s.to_s.rjust(2, "0") }.join(":") unless values[3..5].empty?
|
16
|
+
value
|
17
|
+
end
|
14
18
|
|
15
|
-
|
19
|
+
def instantiate_time_object(set_values)
|
20
|
+
raise if set_values.any?(&:nil?)
|
16
21
|
|
17
|
-
|
18
|
-
|
19
|
-
value += ' ' + values[3..5].map {|s| s.to_s.rjust(2, "0") }.join(":") unless values[3..5].empty?
|
20
|
-
value
|
21
|
-
end
|
22
|
+
validate_multiparameter_date_values(set_values) {
|
23
|
+
set_values = set_values.map {|v| v.is_a?(String) ? v.strip : v }
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
if object.class.send(:create_time_zone_conversion_attribute?, name, cast_type_or_column)
|
26
|
+
Time.zone.local(*set_values)
|
27
|
+
else
|
28
|
+
Time.send(object.class.default_timezone, *set_values)
|
27
29
|
end
|
30
|
+
}
|
31
|
+
rescue
|
32
|
+
invalid_multiparameter_date_or_time_as_string(set_values)
|
33
|
+
end
|
28
34
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
35
|
+
def read_time
|
36
|
+
# If column is a :time (and not :date or :timestamp) there is no need to validate if
|
37
|
+
# there are year/month/day fields
|
38
|
+
if cast_type_or_column.type == :time
|
39
|
+
# if the column is a time set the values to their defaults as January 1, 1970, but only if they're nil
|
40
|
+
{ 1 => 1970, 2 => 1, 3 => 1 }.each do |key,value|
|
41
|
+
values[key] ||= value
|
33
42
|
end
|
43
|
+
end
|
34
44
|
|
35
|
-
|
36
|
-
|
37
|
-
if values[0..2].all?{ |v| v.present? } && Date.valid_civil?(*values[0..2])
|
38
|
-
yield
|
39
|
-
else
|
40
|
-
invalid_multiparameter_date_or_time_as_string(values)
|
41
|
-
end
|
42
|
-
end
|
45
|
+
max_position = extract_max_param(6)
|
46
|
+
set_values = values.values_at(*(1..max_position))
|
43
47
|
|
44
|
-
|
45
|
-
|
46
|
-
values = values_from_param.is_a?(Hash) ? values_from_param.to_a.sort_by(&:first).map(&:last) : values_from_param
|
48
|
+
instantiate_time_object(set_values)
|
49
|
+
end
|
47
50
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
51
|
+
def read_date
|
52
|
+
set_values = values.values_at(1,2,3).map {|v| v.is_a?(String) ? v.strip : v }
|
53
|
+
|
54
|
+
if set_values.any? { |v| v.is_a?(String) }
|
55
|
+
Timeliness.parse(set_values.join('-'), :date).try(:to_date) or raise TypeError
|
56
|
+
else
|
57
|
+
Date.new(*set_values)
|
58
|
+
end
|
59
|
+
rescue TypeError, ArgumentError, NoMethodError => ex # if Date.new raises an exception on an invalid date
|
60
|
+
# Date.new with nil values throws NoMethodError
|
61
|
+
raise ex if ex.is_a?(NoMethodError) && ex.message !~ /undefined method `div' for/
|
62
|
+
invalid_multiparameter_date_or_time_as_string(set_values)
|
63
|
+
end
|
62
64
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
send(name + "=", read_value_from_parameter(name, values_with_empty_parameters))
|
68
|
-
rescue => ex
|
69
|
-
values = values_with_empty_parameters.is_a?(Hash) ? values_with_empty_parameters.values : values_with_empty_parameters
|
70
|
-
errors << ActiveRecord::AttributeAssignmentError.new("error on assignment #{values.inspect} to #{name}", ex, name)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
unless errors.empty?
|
74
|
-
raise ActiveRecord::MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes"
|
75
|
-
end
|
76
|
-
end
|
65
|
+
# Cast type is v4.2 and column before
|
66
|
+
def cast_type_or_column
|
67
|
+
@cast_type || @column
|
68
|
+
end
|
77
69
|
|
78
|
-
|
70
|
+
def timezone_conversion_attribute?
|
71
|
+
object.class.send(:create_time_zone_conversion_attribute?, name, column)
|
79
72
|
end
|
73
|
+
|
80
74
|
end
|