Skip to content

Commit 5783e83

Browse files
committed
Validate when all date parts are set
Co-authored-by: Hugo Melo <[email protected]>
1 parent c75ad16 commit 5783e83

File tree

4 files changed

+1246
-1264
lines changed

4 files changed

+1246
-1264
lines changed

app/models/az321_contribution.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,5 @@ class Az321Contribution < ApplicationRecord
3333
validates :date_of_contribution,
3434
inclusion: {
3535
in: TAX_YEAR.beginning_of_year..TAX_YEAR.end_of_year
36-
},
37-
presence: true
36+
}
3837
end

app/models/concerns/date_accessible.rb

Lines changed: 22 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ module DateAccessible
44
TAX_YEAR = Date.new(Rails.configuration.statefile_current_tax_year)
55

66
included do
7-
private
87

98
# Calls `date_reader` and `date_writer` on specified date properties to set
109
# getters and setters on the specified date properties. For use with
@@ -28,17 +27,7 @@ def self.date_reader(*properties)
2827
properties = [properties] unless properties.is_a?(Enumerable)
2928

3029
properties.each do |property|
31-
self.define_method("#{property}_month") do
32-
send(property)&.month
33-
end
34-
35-
self.define_method("#{property}_year") do
36-
send(property)&.year
37-
end
38-
39-
self.define_method("#{property}_day") do
40-
send(property)&.day
41-
end
30+
attr_reader :"#{property}_month", :"#{property}_year", :"#{property}_day"
4231
end
4332
end
4433

@@ -52,42 +41,32 @@ def self.date_writer(*properties)
5241
properties = [properties] unless properties.is_a?(Enumerable)
5342

5443
properties.each do |property|
55-
self.define_method("#{property}_month=") do |month|
56-
change_date_property(property, month: month) unless month.blank?
57-
end
44+
attr_writer :"#{property}_month", :"#{property}_year", :"#{property}_day"
5845

59-
self.define_method("#{property}_year=") do |year|
60-
change_date_property(property, year: year) unless year.blank?
46+
before_validation do
47+
send(
48+
"#{property}=",
49+
Date.new(
50+
send("#{property}_year").to_i,
51+
send("#{property}_month").to_i,
52+
send("#{property}_day").to_i,
53+
)
54+
)
55+
rescue Date::Error
56+
send("#{property}=", nil)
6157
end
6258

63-
self.define_method("#{property}_day=") do |day|
64-
change_date_property(property, day: day) unless day.blank?
59+
self.class_eval do
60+
validate :"#{property}_date_valid"
61+
62+
define_method("#{property}_date_valid") do
63+
date = send(property)
64+
if date.present? && !Date.valid_date?(date.year, date.month, date.day)
65+
errors.add(property, :invalid_date, message: "is not a valid calendar date")
66+
end
67+
end
6568
end
6669
end
6770
end
68-
69-
# Takes in valid arguments to Date#change. Will create a new date if
70-
# `date_of_contribution` is nil, otherwise will merely modify the correct
71-
# date part. Values can be strings as long as #to_i renders an appropriate
72-
# integer. Note that Date#change only accepts :year, :month, and :day as
73-
# keys, all other keys will be treated as nothing was passed at all.
74-
#
75-
# Note that until all three fragments are passed; month, day, and year
76-
# For year, a range must be indicated on the validator on the property itself
77-
#
78-
# @see Date#change
79-
#
80-
# @param date_property [Symbol] The property to manipulate
81-
# @param args [Hash<Symbol, String | Integer>] Arguments conforming to Date#change
82-
def change_date_property(date_property, args)
83-
existing_date = send(date_property) || Date.new
84-
85-
self.send(
86-
"#{date_property}=",
87-
existing_date.change(**args.transform_values(&:to_i))
88-
)
89-
rescue Date::Error
90-
nil
91-
end
9271
end
9372
end

0 commit comments

Comments
 (0)