diff options
author | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2014-05-20 18:10:54 -0300 |
---|---|---|
committer | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2014-05-20 18:10:54 -0300 |
commit | 52b558695d5a1b33ff21516cbc71d1ae1dee4632 (patch) | |
tree | 3bfcd3aaca10539014e352c5f1582175f42375e6 | |
parent | 90a82cbfb26a24f801864a7fd2664553876b51f3 (diff) | |
parent | 8f387995054d9ce79522da8ef65fba28c6ea0785 (diff) | |
download | rails-52b558695d5a1b33ff21516cbc71d1ae1dee4632.tar.gz rails-52b558695d5a1b33ff21516cbc71d1ae1dee4632.tar.bz2 rails-52b558695d5a1b33ff21516cbc71d1ae1dee4632.zip |
Merge pull request #15207 from sgrif/sg-inline-column-helpers
Inline typecasting helpers from Column to the appropriate types
10 files changed, 77 insertions, 120 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index 0f0aa9110e..9557f41950 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -99,118 +99,6 @@ module ActiveRecord type_cast(default) end - class << self - include Type::TimeValue - - # Used to convert from BLOBs to Strings - def binary_to_string(value) - value - end - - def value_to_date(value) - if value.is_a?(String) - return nil if value.empty? - fast_string_to_date(value) || fallback_string_to_date(value) - elsif value.respond_to?(:to_date) - value.to_date - else - value - end - end - - def string_to_time(string) - return string unless string.is_a?(String) - return nil if string.empty? - - fast_string_to_time(string) || fallback_string_to_time(string) - end - - def string_to_dummy_time(string) - return string unless string.is_a?(String) - return nil if string.empty? - - dummy_time_string = "2000-01-01 #{string}" - - fast_string_to_time(dummy_time_string) || begin - time_hash = Date._parse(dummy_time_string) - return nil if time_hash[:hour].nil? - new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction)) - end - end - - # convert something to a boolean - def value_to_boolean(value) - if value.is_a?(String) && value.empty? - nil - else - TRUE_VALUES.include?(value) - end - end - - # Used to convert values to integer. - # handle the case when an integer column is used to store boolean values - def value_to_integer(value) - case value - when TrueClass, FalseClass - value ? 1 : 0 - else - value.to_i rescue nil - end - end - - # convert something to a BigDecimal - def value_to_decimal(value) - # Using .class is faster than .is_a? and - # subclasses of BigDecimal will be handled - # in the else clause - if value.class == BigDecimal - value - elsif value.respond_to?(:to_d) - value.to_d - else - value.to_s.to_d - end - end - - protected - # '0.123456' -> 123456 - # '1.123456' -> 123456 - def microseconds(time) - time[:sec_fraction] ? (time[:sec_fraction] * 1_000_000).to_i : 0 - end - - def new_date(year, mon, mday) - if year && year != 0 - Date.new(year, mon, mday) rescue nil - end - end - - def fast_string_to_date(string) - if string =~ Format::ISO_DATE - new_date $1.to_i, $2.to_i, $3.to_i - end - end - - # Doesn't handle time zones. - def fast_string_to_time(string) - if string =~ Format::ISO_DATETIME - microsec = ($7.to_r * 1_000_000).to_i - new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec - end - end - - def fallback_string_to_date(string) - new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday)) - end - - def fallback_string_to_time(string) - time_hash = Date._parse(string) - time_hash[:sec_fraction] = microseconds(time_hash) - - new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset)) - end - end - private delegate :extract_scale, to: Type diff --git a/activerecord/lib/active_record/connection_adapters/type/boolean.rb b/activerecord/lib/active_record/connection_adapters/type/boolean.rb index c60a980e80..2337bdd563 100644 --- a/activerecord/lib/active_record/connection_adapters/type/boolean.rb +++ b/activerecord/lib/active_record/connection_adapters/type/boolean.rb @@ -9,7 +9,11 @@ module ActiveRecord private def cast_value(value) - Column.value_to_boolean(value) + if value == '' + nil + else + Column::TRUE_VALUES.include?(value) + end end end end diff --git a/activerecord/lib/active_record/connection_adapters/type/date.rb b/activerecord/lib/active_record/connection_adapters/type/date.rb index 9208da6efe..599dbd320c 100644 --- a/activerecord/lib/active_record/connection_adapters/type/date.rb +++ b/activerecord/lib/active_record/connection_adapters/type/date.rb @@ -9,7 +9,30 @@ module ActiveRecord private def cast_value(value) - Column.value_to_date(value) + if value.is_a?(::String) + return if value.empty? + fast_string_to_date(value) || fallback_string_to_date(value) + elsif value.respond_to?(:to_date) + value.to_date + else + value + end + end + + def fast_string_to_date(string) + if string =~ Column::Format::ISO_DATE + new_date $1.to_i, $2.to_i, $3.to_i + end + end + + def fallback_string_to_date(string) + new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday)) + end + + def new_date(year, mon, mday) + if year && year != 0 + ::Date.new(year, mon, mday) rescue nil + end end end end diff --git a/activerecord/lib/active_record/connection_adapters/type/date_time.rb b/activerecord/lib/active_record/connection_adapters/type/date_time.rb index 757553cd68..c34f4c5a53 100644 --- a/activerecord/lib/active_record/connection_adapters/type/date_time.rb +++ b/activerecord/lib/active_record/connection_adapters/type/date_time.rb @@ -11,7 +11,23 @@ module ActiveRecord private def cast_value(string) - Column.string_to_time(string) + return string unless string.is_a?(::String) + return if string.empty? + + fast_string_to_time(string) || fallback_string_to_time(string) + end + + # '0.123456' -> 123456 + # '1.123456' -> 123456 + def microseconds(time) + time[:sec_fraction] ? (time[:sec_fraction] * 1_000_000).to_i : 0 + end + + def fallback_string_to_time(string) + time_hash = ::Date._parse(string) + time_hash[:sec_fraction] = microseconds(time_hash) + + new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset)) end end end diff --git a/activerecord/lib/active_record/connection_adapters/type/decimal.rb b/activerecord/lib/active_record/connection_adapters/type/decimal.rb index 91957fe84b..6fb1a6c3b0 100644 --- a/activerecord/lib/active_record/connection_adapters/type/decimal.rb +++ b/activerecord/lib/active_record/connection_adapters/type/decimal.rb @@ -11,7 +11,11 @@ module ActiveRecord private def cast_value(value) - Column.value_to_decimal(value) + if value.respond_to?(:to_d) + value.to_d + else + value.to_s.to_d + end end end end diff --git a/activerecord/lib/active_record/connection_adapters/type/integer.rb b/activerecord/lib/active_record/connection_adapters/type/integer.rb index fbc72ae4ef..b41a726ef4 100644 --- a/activerecord/lib/active_record/connection_adapters/type/integer.rb +++ b/activerecord/lib/active_record/connection_adapters/type/integer.rb @@ -11,7 +11,11 @@ module ActiveRecord private def cast_value(value) - Column.value_to_integer(value) + case value + when true then 1 + when false then 0 + else value.to_i rescue nil + end end end end diff --git a/activerecord/lib/active_record/connection_adapters/type/time.rb b/activerecord/lib/active_record/connection_adapters/type/time.rb index b621e8f39c..4dd201e3fe 100644 --- a/activerecord/lib/active_record/connection_adapters/type/time.rb +++ b/activerecord/lib/active_record/connection_adapters/type/time.rb @@ -11,7 +11,16 @@ module ActiveRecord private def cast_value(value) - Column.string_to_dummy_time(value) + return value unless value.is_a?(::String) + return if value.empty? + + dummy_time_value = "2000-01-01 #{value}" + + fast_string_to_time(dummy_time_value) || begin + time_hash = ::Date._parse(dummy_time_value) + return if time_hash[:hour].nil? + new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction)) + end end end end diff --git a/activerecord/lib/active_record/connection_adapters/type/time_value.rb b/activerecord/lib/active_record/connection_adapters/type/time_value.rb index d9564d7f48..654e5c7943 100644 --- a/activerecord/lib/active_record/connection_adapters/type/time_value.rb +++ b/activerecord/lib/active_record/connection_adapters/type/time_value.rb @@ -18,6 +18,14 @@ module ActiveRecord ::Time.public_send(Base.default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil end end + + # Doesn't handle time zones. + def fast_string_to_time(string) + if string =~ Column::Format::ISO_DATETIME + microsec = ($7.to_r * 1_000_000).to_i + new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec + end + end end end end diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index e6195e48a5..29ed499b1b 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -516,7 +516,7 @@ module ActiveRecord # Determines if a hash contains a truthy _destroy key. def has_destroy_flag?(hash) - ConnectionAdapters::Column.value_to_boolean(hash['_destroy']) + ConnectionAdapters::Type::Boolean.new.type_cast(hash['_destroy']) end # Determines if a new record should be rejected by checking diff --git a/activerecord/test/cases/column_test.rb b/activerecord/test/cases/column_test.rb index 15c23ea61d..3257f5bed8 100644 --- a/activerecord/test/cases/column_test.rb +++ b/activerecord/test/cases/column_test.rb @@ -139,7 +139,8 @@ module ActiveRecord def test_string_to_time_with_timezone [:utc, :local].each do |zone| with_timezone_config default: zone do - assert_equal Time.utc(2013, 9, 4, 0, 0, 0), Column.string_to_time("Wed, 04 Sep 2013 03:00:00 EAT") + column = Column.new("field", nil, Type::DateTime.new) + assert_equal Time.utc(2013, 9, 4, 0, 0, 0), column.type_cast("Wed, 04 Sep 2013 03:00:00 EAT") end end end |