correctif(date_champ): renforce la validation avec le parsing de la date plutot qu'une approche par regexp

This commit is contained in:
Martin 2023-01-26 10:53:47 +01:00 committed by Colin Darie
parent 78f9910fd0
commit dbe64cf0c8
2 changed files with 17 additions and 11 deletions

View file

@ -39,7 +39,7 @@ class Champs::DateChamp < Champ
private private
def convert_to_iso8601 def convert_to_iso8601
return if valid_iso8601? return if likely_iso8601_format? && parsable_iso8601?
self.value = if /^\d{2}\/\d{2}\/\d{4}$/.match?(value) self.value = if /^\d{2}\/\d{2}\/\d{4}$/.match?(value)
Date.parse(value).iso8601 Date.parse(value).iso8601
@ -49,12 +49,20 @@ class Champs::DateChamp < Champ
end end
def iso_8601 def iso_8601
return if valid_iso8601? || value.blank? return if parsable_iso8601? || value.blank?
# i18n-tasks-use t('errors.messages.not_a_date') # i18n-tasks-use t('errors.messages.not_a_date')
errors.add :date, errors.generate_message(:value, :not_a_date) errors.add :date, errors.generate_message(:value, :not_a_date)
end end
def valid_iso8601? def likely_iso8601_format?
/^\d{4}-\d{2}-\d{2}$/.match?(value) /^\d{4}-\d{2}-\d{2}$/.match?(value)
end end
def parsable_iso8601?
Date.parse(value)
true
rescue ArgumentError, # case 2023-27-02, out of range
TypeError # nil
false
end
end end

View file

@ -1,5 +1,5 @@
describe Champs::DateChamp do describe Champs::DateChamp do
let(:date_champ) { build(:champ_date) } let(:date_champ) { create(:champ_date) }
describe '#convert_to_iso8601' do describe '#convert_to_iso8601' do
it 'preserves nil' do it 'preserves nil' do
@ -37,16 +37,14 @@ describe Champs::DateChamp do
champ.save champ.save
expect(champ.reload.value).to eq("2023-12-21") expect(champ.reload.value).to eq("2023-12-21")
end end
end
describe 'validate :iso_8601' do it 'converts to nil if false iso' do
it 'works' do champ = champ_with_value("2023-27-02")
date_champ.value = '2023-27-02' champ.save
date_champ.send(:iso_8601) expect(champ.reload.value).to eq(nil)
expect(date_champ.valid?).to eq(false)
expect(date_champ.to_s).not_to raise_error
end end
end end
def champ_with_value(number) def champ_with_value(number)
date_champ.tap { |c| c.value = number } date_champ.tap { |c| c.value = number }
end end