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