From b5c4ef2c785ef634a81d7bb554e9b20f164be95b Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Sat, 24 May 2014 08:23:32 -0700 Subject: Add an interface for type objects to control Ruby => SQL Adds the ability to save custom types, which type cast to non-primitive ruby objects. --- .../lib/active_record/attribute_methods/serialization.rb | 6 ++---- .../lib/active_record/attribute_methods/time_zone_conversion.rb | 6 ++---- .../lib/active_record/connection_adapters/abstract/quoting.rb | 9 +++++++++ activerecord/lib/active_record/connection_adapters/column.rb | 3 ++- activerecord/lib/active_record/connection_adapters/type/value.rb | 4 ++++ activerecord/test/cases/adapters/postgresql/composite_test.rb | 1 - 6 files changed, 19 insertions(+), 10 deletions(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb index 53a9c874bf..47c6f94ba7 100644 --- a/activerecord/lib/active_record/attribute_methods/serialization.rb +++ b/activerecord/lib/active_record/attribute_methods/serialization.rb @@ -65,6 +65,8 @@ module ActiveRecord end class Type # :nodoc: + delegate :type, :type_cast_for_database, to: :@column + def initialize(column) @column = column end @@ -77,10 +79,6 @@ module ActiveRecord end end - def type - @column.type - end - def accessor ActiveRecord::Store::IndifferentHashAccessor end diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb index dfebb2cf56..6149ac4906 100644 --- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb +++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb @@ -2,6 +2,8 @@ module ActiveRecord module AttributeMethods module TimeZoneConversion class Type # :nodoc: + delegate :type, :type_cast_for_database, to: :@column + def initialize(column) @column = column end @@ -10,10 +12,6 @@ module ActiveRecord value = @column.type_cast(value) value.acts_like?(:time) ? value.in_time_zone : value end - - def type - @column.type - end end extend ActiveSupport::Concern diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb index 75501852ed..0bd53a7eb0 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb @@ -47,6 +47,15 @@ module ActiveRecord return value.id end + # FIXME: The only case we get an object other than nil or a real column + # is `SchemaStatements#add_column` with a PG array that has a non-empty default + # value. Is this really the only case? Are we missing tests for other types? + # We should have a real column object passed (or nil) here, and check for that + # instead + if column.respond_to?(:type_cast_for_database) + value = column.type_cast_for_database(value) + end + case value when String, ActiveSupport::Multibyte::Chars value = value.to_s diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index 42aabd6d7f..86232f9d3f 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -18,7 +18,8 @@ module ActiveRecord alias :encoded? :coder - delegate :type, :precision, :scale, :limit, :klass, :text?, :number?, :binary?, :type_cast_for_write, to: :cast_type + delegate :type, :precision, :scale, :limit, :klass, :text?, :number?, :binary?, + :type_cast_for_write, :type_cast_for_database, to: :cast_type # Instantiates a new column in the table. # diff --git a/activerecord/lib/active_record/connection_adapters/type/value.rb b/activerecord/lib/active_record/connection_adapters/type/value.rb index 54a3e9dd7a..9bbc249c2b 100644 --- a/activerecord/lib/active_record/connection_adapters/type/value.rb +++ b/activerecord/lib/active_record/connection_adapters/type/value.rb @@ -21,6 +21,10 @@ module ActiveRecord value end + def type_cast_for_database(value) + type_cast_for_write(value) + end + def text? false end diff --git a/activerecord/test/cases/adapters/postgresql/composite_test.rb b/activerecord/test/cases/adapters/postgresql/composite_test.rb index 1f55cce352..972abf7cdc 100644 --- a/activerecord/test/cases/adapters/postgresql/composite_test.rb +++ b/activerecord/test/cases/adapters/postgresql/composite_test.rb @@ -122,7 +122,6 @@ class PostgresqlCompositeWithCustomOIDTest < ActiveRecord::TestCase assert_equal "Champs-Élysées", composite.address.street composite.address = FullAddress.new("Paris", "Rue Basse") - skip "Saving with custom OID type is currently not supported." composite.save! assert_equal 'Paris', composite.reload.address.city -- cgit v1.2.3