From 0f4b030c44effaea67d6a3d3de5b8a1ae7429088 Mon Sep 17 00:00:00 2001 From: fatkodima Date: Mon, 2 May 2022 19:59:50 +0300 Subject: [PATCH] Fix casting long strings to Date, Time or DateTime --- activemodel/CHANGELOG.md | 4 ++++ activemodel/lib/active_model/type/date.rb | 7 ++++++- activemodel/lib/active_model/type/date_time.rb | 7 ++++++- activemodel/lib/active_model/type/time.rb | 16 ++++++++++++---- activemodel/test/cases/type/date_test.rb | 1 + activemodel/test/cases/type/date_time_test.rb | 1 + activemodel/test/cases/type/time_test.rb | 2 ++ 7 files changed, 32 insertions(+), 6 deletions(-) diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index e0f2a056987..4a57f70a9df 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,7 @@ +* Fix casting long strings to `Date`, `Time` or `DateTime` + + *fatkodima* + * Use different cache namespace for proxy calls Models can currently have different attribute bodies for the same method diff --git a/activemodel/lib/active_model/type/date.rb b/activemodel/lib/active_model/type/date.rb index 465d0b30822..91dce358ad1 100644 --- a/activemodel/lib/active_model/type/date.rb +++ b/activemodel/lib/active_model/type/date.rb @@ -53,7 +53,12 @@ module ActiveModel end def fallback_string_to_date(string) - new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday)) + parts = begin + ::Date._parse(string, false) + rescue ArgumentError + end + + new_date(*parts.values_at(:year, :mon, :mday)) if parts end def new_date(year, mon, mday) diff --git a/activemodel/lib/active_model/type/date_time.rb b/activemodel/lib/active_model/type/date_time.rb index 3a97802f0ce..a9636ca4ec4 100644 --- a/activemodel/lib/active_model/type/date_time.rb +++ b/activemodel/lib/active_model/type/date_time.rb @@ -63,7 +63,12 @@ module ActiveModel end def fallback_string_to_time(string) - time_hash = ::Date._parse(string) + time_hash = begin + ::Date._parse(string) + rescue ArgumentError + end + return unless time_hash + time_hash[:sec_fraction] = microseconds(time_hash) new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset)) diff --git a/activemodel/lib/active_model/type/time.rb b/activemodel/lib/active_model/type/time.rb index 416142d18b8..05a193ae8a9 100644 --- a/activemodel/lib/active_model/type/time.rb +++ b/activemodel/lib/active_model/type/time.rb @@ -54,8 +54,12 @@ module ActiveModel case value when ::String value = "2000-01-01 #{value}" - time_hash = ::Date._parse(value) - return if time_hash[:hour].nil? + time_hash = begin + ::Date._parse(value) + rescue ArgumentError + end + + return if time_hash.nil? || time_hash[:hour].nil? when ::Time value = value.change(year: 2000, day: 1, month: 1) end @@ -71,8 +75,12 @@ module ActiveModel dummy_time_value = value.sub(/\A\d{4}-\d\d-\d\d(?:T|\s)|/, "2000-01-01 ") fast_string_to_time(dummy_time_value) || begin - time_hash = ::Date._parse(dummy_time_value) - return if time_hash[:hour].nil? + time_hash = begin + ::Date._parse(dummy_time_value) + rescue ArgumentError + end + + return if time_hash.nil? || time_hash[:hour].nil? new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset)) end end diff --git a/activemodel/test/cases/type/date_test.rb b/activemodel/test/cases/type/date_test.rb index 2dd1a55616e..80f35f80fc4 100644 --- a/activemodel/test/cases/type/date_test.rb +++ b/activemodel/test/cases/type/date_test.rb @@ -11,6 +11,7 @@ module ActiveModel assert_nil type.cast("") assert_nil type.cast(" ") assert_nil type.cast("ABC") + assert_nil type.cast(" " * 129) now = ::Time.now.utc values_hash = { 1 => now.year, 2 => now.mon, 3 => now.mday } diff --git a/activemodel/test/cases/type/date_time_test.rb b/activemodel/test/cases/type/date_time_test.rb index 4a63eee0cf3..1afe18fabaf 100644 --- a/activemodel/test/cases/type/date_time_test.rb +++ b/activemodel/test/cases/type/date_time_test.rb @@ -11,6 +11,7 @@ module ActiveModel assert_nil type.cast("") assert_nil type.cast(" ") assert_nil type.cast("ABC") + assert_nil type.cast(" " * 129) datetime_string = ::Time.now.utc.strftime("%FT%T") assert_equal datetime_string, type.cast(datetime_string).strftime("%FT%T") diff --git a/activemodel/test/cases/type/time_test.rb b/activemodel/test/cases/type/time_test.rb index 5c6271241d5..7b60f544bf4 100644 --- a/activemodel/test/cases/type/time_test.rb +++ b/activemodel/test/cases/type/time_test.rb @@ -10,6 +10,7 @@ module ActiveModel assert_nil type.cast(nil) assert_nil type.cast("") assert_nil type.cast("ABC") + assert_nil type.cast(" " * 129) time_string = ::Time.now.utc.strftime("%T") assert_equal time_string, type.cast(time_string).strftime("%T") @@ -25,6 +26,7 @@ module ActiveModel assert_nil type.user_input_in_time_zone(nil) assert_nil type.user_input_in_time_zone("") assert_nil type.user_input_in_time_zone("ABC") + assert_nil type.user_input_in_time_zone(" " * 129) offset = ::Time.zone.formatted_offset time_string = "2015-02-09T19:45:54#{offset}"