validates_timeliness 4.1.1 → 5.0.0.alpha1
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 +8 -12
- data/CHANGELOG.rdoc +7 -11
- data/README.rdoc +4 -5
- data/gemfiles/rails_5_0.gemfile +18 -0
- data/gemfiles/rails_5_1.gemfile +18 -0
- data/gemfiles/rails_5_2.gemfile +18 -0
- data/lib/validates_timeliness.rb +1 -1
- data/lib/validates_timeliness/attribute_methods.rb +32 -71
- data/lib/validates_timeliness/{conversion.rb → converter.rb} +26 -14
- data/lib/validates_timeliness/extensions.rb +2 -2
- data/lib/validates_timeliness/extensions/date_time_select.rb +23 -27
- data/lib/validates_timeliness/extensions/multiparameter_handler.rb +47 -66
- data/lib/validates_timeliness/orm/active_model.rb +53 -2
- data/lib/validates_timeliness/orm/active_record.rb +1 -83
- data/lib/validates_timeliness/railtie.rb +0 -8
- data/lib/validates_timeliness/validator.rb +18 -15
- data/lib/validates_timeliness/version.rb +1 -1
- data/spec/spec_helper.rb +2 -2
- data/spec/support/test_model.rb +4 -2
- data/spec/validates_timeliness/attribute_methods_spec.rb +0 -15
- data/spec/validates_timeliness/{conversion_spec.rb → converter_spec.rb} +64 -49
- data/spec/validates_timeliness/extensions/date_time_select_spec.rb +27 -27
- data/spec/validates_timeliness/extensions/multiparameter_handler_spec.rb +10 -10
- data/spec/validates_timeliness/orm/active_record_spec.rb +72 -136
- data/validates_timeliness.gemspec +1 -1
- metadata +15 -21
- data/gemfiles/rails_4_2.gemfile +0 -14
- data/spec/validates_timeliness/railtie_spec.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 66a4ad3b4dbb1cda9d19921e18b17bf30029679689d331aafa699a2a3bb447a5
|
4
|
+
data.tar.gz: 1877d86f268f923d7dd344f2fc6965fbf8d5a207d3d669e3255f094709520a72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3df0f1b7817dbf16b3d9c502488974a2acbbe858d65641a186cf73afb2499d10de484918ff20097396cf2f9295dd88c083de64328510bed53b112e058439663
|
7
|
+
data.tar.gz: 1c9a48cdc41249bed2e75b9087b848e30dd5d9743489bac304aa4a255c374053437f397495b2447ceea1f2af1ae383e5e1b421055d68a86d0abbcde335c7fc46
|
data/.travis.yml
CHANGED
@@ -1,18 +1,14 @@
|
|
1
1
|
language: ruby
|
2
|
-
before_install:
|
3
|
-
- gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
|
4
|
-
- gem install bundler -v '< 2'
|
5
|
-
before_script:
|
6
|
-
- bundle install
|
2
|
+
before_install: gem install bundler
|
7
3
|
cache: bundler
|
8
|
-
bundler_args: --verbose
|
9
4
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
5
|
+
gemfile:
|
6
|
+
- gemfiles/rails_5_0.gemfile
|
7
|
+
- gemfiles/rails_5_1.gemfile
|
8
|
+
- gemfiles/rails_5_2.gemfile
|
9
|
+
|
10
|
+
rvm:
|
11
|
+
- "2.5.1"
|
16
12
|
|
17
13
|
script: 'bundle exec rspec'
|
18
14
|
|
data/CHANGELOG.rdoc
CHANGED
@@ -1,14 +1,10 @@
|
|
1
|
-
=
|
2
|
-
*
|
3
|
-
|
4
|
-
|
5
|
-
*
|
6
|
-
|
7
|
-
|
8
|
-
= 4.1.0 [2019-06-11]
|
9
|
-
* Relaxed Timeliness dependency version to >= 0.3.10 and < 1, which allows
|
10
|
-
version 0.4 with threadsafety fix for use_us_formats and use_euro_formats
|
11
|
-
hot switching in a request.
|
1
|
+
= [UNRELEASED]
|
2
|
+
* Fix DateTimeSelect extension support (AquisTech)
|
3
|
+
|
4
|
+
Breaking Changes
|
5
|
+
* Update Multiparameter extension to use ActiveRecord type classes with multiparameter handling
|
6
|
+
which stores a hash of multiparamter values as the value before type cast, no longer a mushed datetime string
|
7
|
+
* Removed all custom plugin attribute methods and method overrides in favour using ActiveModel type system
|
12
8
|
|
13
9
|
= 4.0.2 [2016-01-07]
|
14
10
|
* Fix undefine_generated_methods ivar guard setting to false
|
data/README.rdoc
CHANGED
@@ -1,14 +1,13 @@
|
|
1
|
-
= ValidatesTimeliness
|
1
|
+
= ValidatesTimeliness {<img src="https://travis-ci.org/adzap/validates_timeliness.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/adzap/validates_timeliness]
|
2
2
|
|
3
3
|
* Source: http://github.com/adzap/validates_timeliness
|
4
4
|
* Issues: http://github.com/adzap/validates_timeliness/issues
|
5
5
|
|
6
6
|
== Description
|
7
7
|
|
8
|
-
Complete validation of dates, times and datetimes for Rails
|
9
|
-
still work but official support has ended.
|
8
|
+
Complete validation of dates, times and datetimes for Rails 5.0.x and ActiveModel.
|
10
9
|
|
11
|
-
If you a looking for the old version for Rails
|
10
|
+
If you a looking for the old version for Rails 4.x go here [https://github.com/adzap/validates_timeliness/tree/4-0-stable].
|
12
11
|
|
13
12
|
|
14
13
|
== Features
|
@@ -31,7 +30,7 @@ If you a looking for the old version for Rails 3.x go here[http://github.com/adz
|
|
31
30
|
== Installation
|
32
31
|
|
33
32
|
# in Gemfile
|
34
|
-
gem 'validates_timeliness', '~>
|
33
|
+
gem 'validates_timeliness', '~> 5.0.0.pre'
|
35
34
|
|
36
35
|
# Run bundler
|
37
36
|
$ bundle install
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "~> 5.0.0"
|
6
|
+
gem "rspec"
|
7
|
+
gem "rspec-rails", "~> 3.7"
|
8
|
+
gem "timecop"
|
9
|
+
gem "byebug"
|
10
|
+
gem "appraisal"
|
11
|
+
gem "sqlite3"
|
12
|
+
gem "nokogiri", "~> 1.8"
|
13
|
+
|
14
|
+
group :active_record do
|
15
|
+
gem "sqlite3-ruby", require: "sqlite3"
|
16
|
+
end
|
17
|
+
|
18
|
+
gemspec path: "../"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "~> 5.1.0"
|
6
|
+
gem "rspec"
|
7
|
+
gem "rspec-rails", "~> 3.7"
|
8
|
+
gem "timecop"
|
9
|
+
gem "byebug"
|
10
|
+
gem "appraisal"
|
11
|
+
gem "sqlite3"
|
12
|
+
gem "nokogiri", "~> 1.8"
|
13
|
+
|
14
|
+
group :active_record do
|
15
|
+
gem "sqlite3-ruby", require: "sqlite3"
|
16
|
+
end
|
17
|
+
|
18
|
+
gemspec path: "../"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "~> 5.2.0"
|
6
|
+
gem "rspec"
|
7
|
+
gem "rspec-rails", "~> 3.7"
|
8
|
+
gem "timecop"
|
9
|
+
gem "byebug"
|
10
|
+
gem "appraisal"
|
11
|
+
gem "sqlite3"
|
12
|
+
gem "nokogiri", "~> 1.8"
|
13
|
+
|
14
|
+
group :active_record do
|
15
|
+
gem "sqlite3-ruby", require: "sqlite3"
|
16
|
+
end
|
17
|
+
|
18
|
+
gemspec path: "../"
|
data/lib/validates_timeliness.rb
CHANGED
@@ -62,7 +62,7 @@ module ValidatesTimeliness
|
|
62
62
|
def self.parser; Timeliness end
|
63
63
|
end
|
64
64
|
|
65
|
-
require 'validates_timeliness/
|
65
|
+
require 'validates_timeliness/converter'
|
66
66
|
require 'validates_timeliness/validator'
|
67
67
|
require 'validates_timeliness/helper_methods'
|
68
68
|
require 'validates_timeliness/attribute_methods'
|
@@ -6,83 +6,44 @@ module ValidatesTimeliness
|
|
6
6
|
class_attribute :timeliness_validated_attributes
|
7
7
|
self.timeliness_validated_attributes = []
|
8
8
|
end
|
9
|
+
end
|
10
|
+
end
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
def timeliness_attribute_timezone_aware?(attr_name)
|
15
|
-
false
|
16
|
-
end
|
17
|
-
|
18
|
-
# Override in ORM shim
|
19
|
-
def timeliness_attribute_type(attr_name)
|
20
|
-
:datetime
|
21
|
-
end
|
22
|
-
|
23
|
-
def define_timeliness_methods(before_type_cast=false)
|
24
|
-
return if timeliness_validated_attributes.blank?
|
25
|
-
timeliness_validated_attributes.each do |attr_name|
|
26
|
-
define_attribute_timeliness_methods(attr_name, before_type_cast)
|
27
|
-
end
|
28
|
-
end
|
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_timeliness_attribute_methods
|
37
|
-
generated_timeliness_methods.module_eval do
|
38
|
-
instance_methods.each { |m| undef_method(m) }
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
protected
|
43
|
-
|
44
|
-
def define_attribute_timeliness_methods(attr_name, before_type_cast=false)
|
45
|
-
define_timeliness_write_method(attr_name)
|
46
|
-
define_timeliness_before_type_cast_method(attr_name) if before_type_cast
|
47
|
-
end
|
48
|
-
|
49
|
-
def define_timeliness_write_method(attr_name)
|
50
|
-
generated_timeliness_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
51
|
-
def #{attr_name}=(value)
|
52
|
-
write_timeliness_attribute('#{attr_name}', value)
|
53
|
-
end
|
54
|
-
STR
|
55
|
-
end
|
56
|
-
|
57
|
-
def define_timeliness_before_type_cast_method(attr_name)
|
58
|
-
generated_timeliness_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
59
|
-
def #{attr_name}_before_type_cast
|
60
|
-
read_timeliness_attribute_before_type_cast('#{attr_name}')
|
61
|
-
end
|
62
|
-
STR
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def write_timeliness_attribute(attr_name, value)
|
67
|
-
@timeliness_cache ||= {}
|
68
|
-
@timeliness_cache[attr_name] = value
|
12
|
+
ActiveModel::Type::Date.class_eval do
|
13
|
+
# Module.new do |m|
|
14
|
+
def cast_value(value)
|
15
|
+
return super unless ValidatesTimeliness.use_plugin_parser
|
69
16
|
|
70
|
-
if
|
71
|
-
|
72
|
-
|
73
|
-
value
|
74
|
-
|
17
|
+
if value.is_a?(::String)
|
18
|
+
return if value.empty?
|
19
|
+
value = Timeliness::Parser.parse(value, :date)
|
20
|
+
value.to_date if value
|
21
|
+
elsif value.respond_to?(:to_date)
|
22
|
+
value.to_date
|
23
|
+
else
|
24
|
+
value
|
75
25
|
end
|
76
|
-
|
77
|
-
@attributes[attr_name] = value
|
78
26
|
end
|
27
|
+
# end.tap { |mod| include mod }
|
28
|
+
end
|
79
29
|
|
80
|
-
|
81
|
-
|
30
|
+
ActiveModel::Type::Time.class_eval do
|
31
|
+
def user_input_in_time_zone(value)
|
32
|
+
if value.is_a?(String) && ValidatesTimeliness.use_plugin_parser
|
33
|
+
dummy_time_value = value.sub(/\A(\d\d\d\d-\d\d-\d\d |)/, Date.current.to_s + ' ')
|
34
|
+
Timeliness::Parser.parse(dummy_time_value, :datetime, zone: :current)
|
35
|
+
else
|
36
|
+
value.in_time_zone
|
82
37
|
end
|
38
|
+
end
|
39
|
+
end
|
83
40
|
|
84
|
-
|
85
|
-
|
41
|
+
ActiveModel::Type::DateTime.class_eval do
|
42
|
+
def user_input_in_time_zone(value)
|
43
|
+
if value.is_a?(String) && ValidatesTimeliness.use_plugin_parser
|
44
|
+
Timeliness::Parser.parse(value, :datetime, zone: :current)
|
45
|
+
else
|
46
|
+
value.in_time_zone
|
86
47
|
end
|
87
48
|
end
|
88
|
-
end
|
49
|
+
end
|
@@ -1,10 +1,18 @@
|
|
1
1
|
module ValidatesTimeliness
|
2
|
-
|
2
|
+
class Converter
|
3
|
+
attr_reader :type, :format, :ignore_usec
|
3
4
|
|
4
|
-
def
|
5
|
+
def initialize(type:, format: nil, ignore_usec: false, time_zone_aware: false)
|
6
|
+
@type = type
|
7
|
+
@format = format
|
8
|
+
@ignore_usec = ignore_usec
|
9
|
+
@time_zone_aware = time_zone_aware
|
10
|
+
end
|
11
|
+
|
12
|
+
def type_cast_value(value)
|
5
13
|
return nil if value.nil? || !value.respond_to?(:to_time)
|
6
14
|
|
7
|
-
value = value.in_time_zone if value.acts_like?(:time) &&
|
15
|
+
value = value.in_time_zone if value.acts_like?(:time) && time_zone_aware?
|
8
16
|
value = case type
|
9
17
|
when :time
|
10
18
|
dummy_time(value)
|
@@ -15,8 +23,8 @@ module ValidatesTimeliness
|
|
15
23
|
else
|
16
24
|
value
|
17
25
|
end
|
18
|
-
if
|
19
|
-
Timeliness::Parser.make_time(Array(value).reverse[4..9], (:current if
|
26
|
+
if ignore_usec && value.is_a?(Time)
|
27
|
+
Timeliness::Parser.make_time(Array(value).reverse[4..9], (:current if time_zone_aware?))
|
20
28
|
else
|
21
29
|
value
|
22
30
|
end
|
@@ -24,30 +32,30 @@ module ValidatesTimeliness
|
|
24
32
|
|
25
33
|
def dummy_time(value)
|
26
34
|
time = if value.acts_like?(:time)
|
27
|
-
value = value.in_time_zone if
|
35
|
+
value = value.in_time_zone if time_zone_aware?
|
28
36
|
[value.hour, value.min, value.sec]
|
29
37
|
else
|
30
38
|
[0,0,0]
|
31
39
|
end
|
32
40
|
values = ValidatesTimeliness.dummy_date_for_time_type + time
|
33
|
-
Timeliness::Parser.make_time(values, (:current if
|
41
|
+
Timeliness::Parser.make_time(values, (:current if time_zone_aware?))
|
34
42
|
end
|
35
43
|
|
36
|
-
def
|
44
|
+
def evaluate(value, scope=nil)
|
37
45
|
case value
|
38
46
|
when Time, Date
|
39
47
|
value
|
40
48
|
when String
|
41
49
|
parse(value)
|
42
50
|
when Symbol
|
43
|
-
if !
|
51
|
+
if !scope.respond_to?(value) && restriction_shorthand?(value)
|
44
52
|
ValidatesTimeliness.restriction_shorthand_symbols[value].call
|
45
53
|
else
|
46
|
-
|
54
|
+
evaluate(scope.send(value))
|
47
55
|
end
|
48
56
|
when Proc
|
49
|
-
result = value.arity > 0 ? value.call(
|
50
|
-
|
57
|
+
result = value.arity > 0 ? value.call(scope) : value.call
|
58
|
+
evaluate(result, scope)
|
51
59
|
else
|
52
60
|
value
|
53
61
|
end
|
@@ -59,14 +67,18 @@ module ValidatesTimeliness
|
|
59
67
|
|
60
68
|
def parse(value)
|
61
69
|
return nil if value.nil?
|
70
|
+
|
62
71
|
if ValidatesTimeliness.use_plugin_parser
|
63
|
-
Timeliness::Parser.parse(value,
|
72
|
+
Timeliness::Parser.parse(value, type, zone: (:current if time_zone_aware?), format: format, strict: false)
|
64
73
|
else
|
65
|
-
|
74
|
+
time_zone_aware? ? Time.zone.parse(value) : value.to_time(ValidatesTimeliness.default_timezone)
|
66
75
|
end
|
67
76
|
rescue ArgumentError, TypeError
|
68
77
|
nil
|
69
78
|
end
|
70
79
|
|
80
|
+
def time_zone_aware?
|
81
|
+
@time_zone_aware
|
82
|
+
end
|
71
83
|
end
|
72
84
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module ValidatesTimeliness
|
2
2
|
module Extensions
|
3
|
-
autoload :
|
3
|
+
autoload :TimelinessDateTimeSelect, 'validates_timeliness/extensions/date_time_select'
|
4
4
|
end
|
5
5
|
|
6
6
|
def self.enable_date_time_select_extension!
|
7
|
-
::ActionView::Helpers::Tags::DateSelect.send(:
|
7
|
+
::ActionView::Helpers::Tags::DateSelect.send(:prepend, ValidatesTimeliness::Extensions::TimelinessDateTimeSelect)
|
8
8
|
end
|
9
9
|
|
10
10
|
def self.enable_multiparameter_extension!
|
@@ -1,54 +1,50 @@
|
|
1
1
|
module ValidatesTimeliness
|
2
2
|
module Extensions
|
3
|
-
module
|
4
|
-
extend ActiveSupport::Concern
|
5
|
-
|
3
|
+
module TimelinessDateTimeSelect
|
6
4
|
# Intercepts the date and time select helpers to reuse the values from
|
7
5
|
# the params rather than the parsed value. This allows invalid date/time
|
8
6
|
# values to be redisplayed instead of blanks to aid correction by the user.
|
9
7
|
# It's a minor usability improvement which is rarely an issue for the user.
|
8
|
+
attr_accessor :object_name, :method_name, :template_object, :options, :html_options
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
POSITION = {
|
11
|
+
:year => 1, :month => 2, :day => 3, :hour => 4, :min => 5, :sec => 6
|
12
|
+
}.freeze
|
14
13
|
|
15
|
-
class
|
14
|
+
class DateTimeValue
|
16
15
|
attr_accessor :year, :month, :day, :hour, :min, :sec
|
17
16
|
|
18
|
-
def initialize(year
|
17
|
+
def initialize(year:, month:, day: nil, hour: nil, min: nil, sec: nil)
|
19
18
|
@year, @month, @day, @hour, @min, @sec = year, month, day, hour, min, sec
|
20
19
|
end
|
21
20
|
|
22
|
-
# adapted from activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 36 (3.0.7)
|
23
21
|
def change(options)
|
24
|
-
|
25
|
-
options
|
26
|
-
options
|
27
|
-
options
|
28
|
-
options
|
29
|
-
options
|
30
|
-
options
|
22
|
+
self.class.new(
|
23
|
+
year: options.fetch(:year, year),
|
24
|
+
month: options.fetch(:month, month),
|
25
|
+
day: options.fetch(:day, day),
|
26
|
+
hour: options.fetch(:hour, hour),
|
27
|
+
min: options.fetch(:min) { options[:hour] ? 0 : min },
|
28
|
+
sec: options.fetch(:sec) { options[:hour] || options[:min] ? 0 : sec }
|
31
29
|
)
|
32
30
|
end
|
33
31
|
end
|
34
32
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
@template_object.params[@object_name]
|
33
|
+
# Splat args to support Rails 5.0 which expects object, and 5.2 which doesn't
|
34
|
+
def value(*object)
|
35
|
+
return super unless @template_object.params[@object_name]
|
39
36
|
|
40
37
|
pairs = @template_object.params[@object_name].select {|k,v| k =~ /^#{@method_name}\(/ }
|
41
|
-
return
|
38
|
+
return super if pairs.empty?
|
42
39
|
|
43
|
-
values =
|
44
|
-
pairs.
|
45
|
-
position =
|
46
|
-
values[position.to_i
|
40
|
+
values = {}
|
41
|
+
pairs.each_pair do |key, value|
|
42
|
+
position = key[/\((\d+)\w+\)/, 1]
|
43
|
+
values[POSITION.key(position.to_i)] = value.to_i
|
47
44
|
end
|
48
45
|
|
49
|
-
|
46
|
+
DateTimeValue.new(values)
|
50
47
|
end
|
51
|
-
|
52
48
|
end
|
53
49
|
end
|
54
50
|
end
|