validates_timeliness 7.0.0.beta2 → 7.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 291ec2c50666a8ce39654fb9c065ca22a27cc91413039a41faa1045e5143ee7e
4
- data.tar.gz: 8ec042268f1524503c5daf4e0038769d64b0be9b0329281137a569579a5d991a
3
+ metadata.gz: d882843a354b86918dd2709809168d5dcbaf024319eeb424b1e0ff56f7731512
4
+ data.tar.gz: 0d5c06701e489c7332b59032055a25bcd4c2887f68c95b49a2d4192ecf313d71
5
5
  SHA512:
6
- metadata.gz: 0f7fd09d93f725dcbda325d6d681f1f68fd765ea75a5ae8d3206fe369fd9647f1ae6cb1be36d353c790482e310bd4f8cd4cc749fbb75a8aafc8b4653f7e76025
7
- data.tar.gz: 433b16c8be0034ca7e9d8f6349ee9423a1437df4183e47efd623116b634287833f7b57f7f7a456bff06a1bbb9eb19df14c5cf73a0a6bb1e46d52f3ff112522df
6
+ metadata.gz: dc46ee39a4f707078094de96dd795c75f6287343c3a020be49a8455c76a07aad0cd4d26d46b143ca4149c81a8d54c273a32575ef7f0bc23fa63317ccaffc1851
7
+ data.tar.gz: 68a0b32a966d7c1a3df5d33c7642eac1c92efa276059b543b8240e73535fa5538e51c580be3362c4011b8f1838bc03817e7b7cc07d7219e68a18b2299cacf6a3
@@ -14,6 +14,22 @@ jobs:
14
14
  - gemfile: rails_7_0
15
15
  ruby: 3.1
16
16
 
17
+ - gemfile: rails_7_1
18
+ ruby: 2.7
19
+ - gemfile: rails_7_1
20
+ ruby: 3.0
21
+ - gemfile: rails_7_1
22
+ ruby: 3.1
23
+ - gemfile: rails_7_1
24
+ ruby: 3.2
25
+
26
+ - gemfile: rails_7_2
27
+ ruby: 3.1
28
+ - gemfile: rails_7_2
29
+ ruby: 3.2
30
+ - gemfile: rails_7_2
31
+ ruby: 3.3
32
+
17
33
  name: ${{ matrix.gemfile }}, ruby ${{ matrix.ruby }}
18
34
  env:
19
35
  BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
data/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ # 7.1.0 [2024-12-31]
2
+ * Support passing non-reserved validation options to errors
3
+
4
+ # 7.0.0 [2024-11-30]
5
+ * Support Rails v7.x
6
+ * Removed all method overrides in ActiveModel now that the datetime type correctly stores before_type_cast values.
7
+
8
+ # 6.0.1 [2023-01-12]
9
+ * TODO need to complete this
10
+
11
+ # 6.0.0 [2022-10-20]
12
+ * TODO need to complete this
13
+
1
14
  # 5.0.0 [2021-04-03]
2
15
  * Fix DateTimeSelect extension support (AquisTech)
3
16
  * Relaxed Timeliness dependency version which allows for >= 0.4.0 with
data/README.md CHANGED
@@ -30,7 +30,7 @@ Older Rails versions:
30
30
 
31
31
  In Gemfile
32
32
  ```ruby
33
- gem 'validates_timeliness', '~> 7.0.0.beta1'
33
+ gem 'validates_timeliness', '~> 7.0.0'
34
34
  ```
35
35
 
36
36
  Run bundler:
@@ -1,13 +1,13 @@
1
1
  # This file was generated by Appraisal
2
2
 
3
- source "http://rubygems.org"
3
+ source "https://rubygems.org"
4
4
 
5
5
  gem "rails", "~> 7.0.0"
6
6
  gem "rspec"
7
7
  gem "rspec-rails", "~> 6.0"
8
- gem "sqlite3"
8
+ gem "sqlite3", "~> 1.4"
9
9
  gem "byebug"
10
10
  gem "appraisal"
11
- gem "nokogiri", "~> 1.8"
11
+ gem "nokogiri"
12
12
 
13
13
  gemspec path: "../"
@@ -0,0 +1,13 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 7.1.0"
6
+ gem "rspec"
7
+ gem "rspec-rails", "~> 6.0"
8
+ gem "sqlite3", "~> 1.4"
9
+ gem "byebug"
10
+ gem "appraisal"
11
+ gem "nokogiri"
12
+
13
+ gemspec path: "../"
@@ -0,0 +1,13 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 7.2.0"
6
+ gem "rspec"
7
+ gem "rspec-rails", "~> 6.0"
8
+ gem "sqlite3", "~> 1.4"
9
+ gem "byebug"
10
+ gem "appraisal"
11
+ gem "nokogiri"
12
+
13
+ gemspec path: "../"
@@ -1,6 +1,6 @@
1
1
  module ValidatesTimeliness
2
2
  module Extensions
3
- module TimelinessDateTimeSelect
3
+ module DateTimeSelect
4
4
  # Intercepts the date and time select helpers to reuse the values from
5
5
  # the params rather than the parsed value. This allows invalid date/time
6
6
  # values to be redisplayed instead of blanks to aid correction by the user.
@@ -1,10 +1,11 @@
1
1
  module ValidatesTimeliness
2
2
  module Extensions
3
- autoload :TimelinessDateTimeSelect, 'validates_timeliness/extensions/date_time_select'
3
+ autoload :DateTimeSelect, '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(:prepend, ValidatesTimeliness::Extensions::TimelinessDateTimeSelect)
7
+ require 'uri' # Do we need this? No, but the test suite fails without it.
8
+ ::ActionView::Helpers::Tags::DateSelect.send(:prepend, ValidatesTimeliness::Extensions::DateTimeSelect)
8
9
  end
9
10
 
10
11
  def self.enable_multiparameter_extension!
@@ -3,25 +3,19 @@ module ActiveModel
3
3
 
4
4
  module HelperMethods
5
5
  def validates_date(*attr_names)
6
- timeliness_validation_for attr_names, :date
6
+ validates_with TimelinessValidator, _merge_attributes(attr_names).merge(type: :date)
7
7
  end
8
8
 
9
9
  def validates_time(*attr_names)
10
- timeliness_validation_for attr_names, :time
10
+ validates_with TimelinessValidator, _merge_attributes(attr_names).merge(type: :time)
11
11
  end
12
12
 
13
13
  def validates_datetime(*attr_names)
14
- timeliness_validation_for attr_names, :datetime
14
+ validates_with TimelinessValidator, _merge_attributes(attr_names).merge(type: :datetime)
15
15
  end
16
16
 
17
17
  def validates_timeliness_of(*attr_names)
18
- timeliness_validation_for attr_names
19
- end
20
-
21
- def timeliness_validation_for(attr_names, type=nil)
22
- options = _merge_attributes(attr_names)
23
- options.update(:type => type) if type
24
- validates_with TimelinessValidator, options
18
+ validates_with TimelinessValidator, _merge_attributes(attr_names)
25
19
  end
26
20
  end
27
21
 
@@ -3,91 +3,8 @@ module ValidatesTimeliness
3
3
  module ActiveModel
4
4
  extend ActiveSupport::Concern
5
5
 
6
- module ClassMethods
7
- public
8
-
9
- # Hook into bulk method definitions for non-attribute based methods validated.
10
- def define_attribute_methods(*attr_names)
11
- super.tap {
12
- define_timeliness_methods
13
- }
14
- end
15
-
16
- # Called when `attribute` methods is called and the timeliness overrides are defined here
17
- def define_attribute_method(attr_name)
18
- super.tap {
19
- define_attribute_timeliness_methods(attr_name)
20
- }
21
- end
22
-
23
- def undefine_attribute_methods
24
- super.tap {
25
- undefine_timeliness_attribute_methods
26
- }
27
- end
28
-
29
- def define_timeliness_methods(before_type_cast=false)
30
- return if timeliness_validated_attributes.blank?
31
-
32
- timeliness_validated_attributes.each do |attr_name|
33
- unless timeliness_method_already_implemented?(attr_name)
34
- define_attribute_timeliness_methods(attr_name, before_type_cast)
35
- end
36
- end
37
- end
38
-
39
- def define_timeliness_method(attr_name, before_type_cast=false)
40
- define_attribute_timeliness_methods(attr_name, before_type_cast)
41
- end
42
-
43
- # Lazy instantiate module as container of timeliness methods included in the model
44
- def generated_timeliness_methods
45
- @generated_timeliness_methods ||= Module.new { |m|
46
- extend Mutex_m
47
- }.tap { |mod| include mod }
48
- end
49
-
50
- def timeliness_method_already_implemented?(method_name)
51
- generated_timeliness_methods.method_defined?(method_name)
52
- end
53
-
54
- def undefine_timeliness_attribute_methods
55
- generated_timeliness_methods.module_eval do
56
- undef_method(*instance_methods)
57
- end
58
- end
59
-
60
- def define_attribute_timeliness_methods(attr_name, before_type_cast=false)
61
- define_timeliness_write_method(attr_name)
62
- define_timeliness_before_type_cast_method(attr_name) if before_type_cast
63
- end
64
-
65
- def define_timeliness_write_method(attr_name)
66
- generated_timeliness_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
67
- def #{attr_name}=(value)
68
- @timeliness_cache ||= {}
69
- @timeliness_cache['#{attr_name}'] = value
70
-
71
- super
72
- end
73
- STR
74
- end
75
-
76
- def define_timeliness_before_type_cast_method(attr_name)
77
- generated_timeliness_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
78
- def #{attr_name}_before_type_cast
79
- read_timeliness_attribute_before_type_cast('#{attr_name}')
80
- end
81
- STR
82
- end
83
- end
84
-
85
6
  def read_timeliness_attribute_before_type_cast(attr_name)
86
- @timeliness_cache && @timeliness_cache[attr_name] || @attributes[attr_name].value_before_type_cast
87
- end
88
-
89
- def _clear_timeliness_cache
90
- @timeliness_cache = {}
7
+ @attributes[attr_name].value_before_type_cast
91
8
  end
92
9
 
93
10
  end
@@ -21,6 +21,8 @@ module ValidatesTimeliness
21
21
 
22
22
  RESTRICTION_ERROR_MESSAGE = "Error occurred validating %s for %s restriction:\n%s"
23
23
 
24
+ RESERVED_OPTIONS = RESTRICTIONS.keys + RESTRICTIONS.keys.map { |option| :"#{option}_message" }
25
+
24
26
  def self.kind
25
27
  :timeliness
26
28
  end
@@ -72,7 +74,7 @@ module ValidatesTimeliness
72
74
  begin
73
75
  restriction_value = @converter.type_cast_value(@converter.evaluate(options[restriction], record))
74
76
  unless value.send(RESTRICTIONS[restriction], restriction_value)
75
- add_error(record, attr_name, restriction, restriction_value) and break
77
+ add_error(record, attr_name, restriction, value: value, restriction_value: restriction_value) and break
76
78
  end
77
79
  rescue => e
78
80
  unless ValidatesTimeliness.ignore_restriction_errors
@@ -83,20 +85,28 @@ module ValidatesTimeliness
83
85
  end
84
86
  end
85
87
 
86
- def add_error(record, attr_name, message, value=nil)
87
- value = format_error_value(value) if value
88
- message_options = { message: options.fetch(:"#{message}_message", options[:message]), restriction: value }
89
- record.errors.add(attr_name, message, **message_options)
88
+ def add_error(record, attr_name, message, restriction_value: nil, value: nil)
89
+ error_options = options.except(*RESERVED_OPTIONS).merge!(
90
+ restriction: format_error_value(restriction_value),
91
+ value: value
92
+ )
93
+
94
+ message_text = options[:"#{message}_message"]
95
+ error_options[:message] = message_text if message_text.present?
96
+
97
+ record.errors.add(attr_name, message, **error_options)
90
98
  end
91
99
 
92
100
  def format_error_value(value)
101
+ return unless value
93
102
  format = I18n.t(@type, default: DEFAULT_ERROR_VALUE_FORMATS[@type], scope: 'validates_timeliness.error_value_formats')
94
103
  value.strftime(format)
95
104
  end
96
105
 
97
106
  def attribute_raw_value(record, attr_name)
98
- record.respond_to?(:read_timeliness_attribute_before_type_cast) &&
107
+ if record.respond_to?(:read_timeliness_attribute_before_type_cast)
99
108
  record.read_timeliness_attribute_before_type_cast(attr_name.to_s)
109
+ end
100
110
  end
101
111
 
102
112
  def time_zone_aware?(record, attr_name)
@@ -1,3 +1,3 @@
1
1
  module ValidatesTimeliness
2
- VERSION = '7.0.0.beta2'
2
+ VERSION = '7.1.0'
3
3
  end
@@ -185,6 +185,26 @@ RSpec.describe ValidatesTimeliness::Validator do
185
185
  end
186
186
  end
187
187
 
188
+ describe "custom option" do
189
+ it "should pass custom options to the error" do
190
+ Person.validates_datetime :birth_datetime, :on_or_before => Time.utc(2010,1,2,3,4,5), :custom => 'option'
191
+
192
+ with_each_model_value(:birth_datetime, Time.utc(2010,1,2,3,4,5,10000), Person) do |record, value|
193
+ expect(record).to_not be_valid
194
+ expect(record.errors.where(:birth_datetime).first.options).to include(custom: 'option')
195
+ end
196
+ end
197
+
198
+ it "should not pass config options to the error" do
199
+ Person.validates_datetime :birth_datetime, :on_or_before => Time.utc(2010,1,2,3,4,5), :custom => 'option'
200
+
201
+ with_each_model_value(:birth_datetime, Time.utc(2010,1,2,3,4,5,10000), Person) do |record, value|
202
+ expect(record).to_not be_valid
203
+ expect(record.errors.where(:birth_datetime).first.options.keys).to_not include(:on_or_before)
204
+ end
205
+ end
206
+ end
207
+
188
208
  describe "restriction value errors" do
189
209
  let(:person) { Person.new(:birth_date => Date.today) }
190
210
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: validates_timeliness
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.0.beta2
4
+ version: 7.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Meehan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-24 00:00:00.000000000 Z
11
+ date: 2024-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -67,7 +67,8 @@ files:
67
67
  - README.md
68
68
  - Rakefile
69
69
  - gemfiles/rails_7_0.gemfile
70
- - gemfiles/rails_edge.gemfile
70
+ - gemfiles/rails_7_1.gemfile
71
+ - gemfiles/rails_7_2.gemfile
71
72
  - init.rb
72
73
  - lib/generators/validates_timeliness/install_generator.rb
73
74
  - lib/generators/validates_timeliness/templates/en.yml
@@ -126,11 +127,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
126
127
  version: '0'
127
128
  required_rubygems_version: !ruby/object:Gem::Requirement
128
129
  requirements:
129
- - - ">"
130
+ - - ">="
130
131
  - !ruby/object:Gem::Version
131
- version: 1.3.1
132
+ version: '0'
132
133
  requirements: []
133
- rubygems_version: 3.1.6
134
+ rubygems_version: 3.4.19
134
135
  signing_key:
135
136
  specification_version: 4
136
137
  summary: Date and time validation plugin for Rails which allows custom formats
@@ -1,13 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "http://rubygems.org"
4
-
5
- gem "rails", git: "https://github.com/rails/rails.git", branch: "main"
6
- gem "rspec"
7
- gem "rspec-rails", "~> 3.7"
8
- gem "sqlite3"
9
- gem "byebug"
10
- gem "appraisal"
11
- gem "nokogiri", "~> 1.8"
12
-
13
- gemspec path: "../"