Skip to content

Commit

Permalink
Validate when all date parts are set
Browse files Browse the repository at this point in the history
Co-authored-by: Hugo Melo <[email protected]>
  • Loading branch information
squanto committed Feb 12, 2025
1 parent c75ad16 commit 5783e83
Show file tree
Hide file tree
Showing 4 changed files with 1,246 additions and 1,264 deletions.
3 changes: 1 addition & 2 deletions app/models/az321_contribution.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,5 @@ class Az321Contribution < ApplicationRecord
validates :date_of_contribution,
inclusion: {
in: TAX_YEAR.beginning_of_year..TAX_YEAR.end_of_year
},
presence: true
}
end
65 changes: 22 additions & 43 deletions app/models/concerns/date_accessible.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ module DateAccessible
TAX_YEAR = Date.new(Rails.configuration.statefile_current_tax_year)

included do
private

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

properties.each do |property|
self.define_method("#{property}_month") do
send(property)&.month
end

self.define_method("#{property}_year") do
send(property)&.year
end

self.define_method("#{property}_day") do
send(property)&.day
end
attr_reader :"#{property}_month", :"#{property}_year", :"#{property}_day"
end
end

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

properties.each do |property|
self.define_method("#{property}_month=") do |month|
change_date_property(property, month: month) unless month.blank?
end
attr_writer :"#{property}_month", :"#{property}_year", :"#{property}_day"

self.define_method("#{property}_year=") do |year|
change_date_property(property, year: year) unless year.blank?
before_validation do
send(
"#{property}=",
Date.new(
send("#{property}_year").to_i,
send("#{property}_month").to_i,
send("#{property}_day").to_i,
)
)
rescue Date::Error
send("#{property}=", nil)
end

self.define_method("#{property}_day=") do |day|
change_date_property(property, day: day) unless day.blank?
self.class_eval do
validate :"#{property}_date_valid"

define_method("#{property}_date_valid") do
date = send(property)
if date.present? && !Date.valid_date?(date.year, date.month, date.day)
errors.add(property, :invalid_date, message: "is not a valid calendar date")
end
end
end
end
end

# Takes in valid arguments to Date#change. Will create a new date if
# `date_of_contribution` is nil, otherwise will merely modify the correct
# date part. Values can be strings as long as #to_i renders an appropriate
# integer. Note that Date#change only accepts :year, :month, and :day as
# keys, all other keys will be treated as nothing was passed at all.
#
# Note that until all three fragments are passed; month, day, and year
# For year, a range must be indicated on the validator on the property itself
#
# @see Date#change
#
# @param date_property [Symbol] The property to manipulate
# @param args [Hash<Symbol, String | Integer>] Arguments conforming to Date#change
def change_date_property(date_property, args)
existing_date = send(date_property) || Date.new

self.send(
"#{date_property}=",
existing_date.change(**args.transform_values(&:to_i))
)
rescue Date::Error
nil
end
end
end
Loading

0 comments on commit 5783e83

Please sign in to comment.