aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/lib/active_record/connection_adapters/column.rb112
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/boolean.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/date.rb25
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/date_time.rb18
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/decimal.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/integer.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/time.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/time_value.rb8
-rw-r--r--activerecord/lib/active_record/nested_attributes.rb2
-rw-r--r--activerecord/test/cases/column_test.rb3
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