validates_timeliness 3.0.15 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|