validates_timeliness 7.0.0.beta2 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: "../"