From d9314b4c0a8b32f242ed4d394dcc3d45ddfb4c62 Mon Sep 17 00:00:00 2001 From: Yves Senn Date: Wed, 7 Aug 2013 18:56:49 +0200 Subject: Coerce strings when reading attributes. --- activerecord/CHANGELOG.md | 11 +++++++++++ .../lib/active_record/connection_adapters/column.rb | 10 ++++++++-- .../connection_adapters/postgresql/oid.rb | 18 +++++++++++++----- activerecord/test/cases/attribute_methods_test.rb | 18 ++++++++++++++++++ 4 files changed, 50 insertions(+), 7 deletions(-) (limited to 'activerecord') diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 881a4d2d85..7be5278a54 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,14 @@ +* Coerce strings when reading attributes. + Fixes #10485. + + Example: + + book = Book.new(title: 12345) + book.save! + book.title # => "12345" + + *Yves Senn* + * Deprecate half-baked support for PostgreSQL range values with excluding beginnings. We currently map PostgreSQL ranges to Ruby ranges. This conversion is not fully possible because the Ruby range does not support excluded beginnings. diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index f2fbd5a8f2..187eefb9e4 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -87,7 +87,7 @@ module ActiveRecord end end - # Casts value (which is a String) to an appropriate instance. + # Casts value to an appropriate instance. def type_cast(value) return nil if value.nil? return coder.load(value) if encoded? @@ -95,7 +95,13 @@ module ActiveRecord klass = self.class case type - when :string, :text then value + when :string, :text + case value + when TrueClass; "1" + when FalseClass; "0" + else + value.to_s + end when :integer then klass.value_to_integer(value) when :float then value.to_f when :decimal then klass.value_to_decimal(value) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb index 6f9b60b6c4..e7df073627 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb @@ -18,6 +18,14 @@ module ActiveRecord end end + class Text < Type + def type_cast(value) + return if value.nil? + + value.to_s + end + end + class Bit < Type def type_cast(value) if String === value @@ -329,7 +337,7 @@ This is not reliable and will be removed in the future. alias_type 'oid', 'int2' register_type 'numeric', OID::Decimal.new - register_type 'text', OID::Identity.new + register_type 'text', OID::Text.new alias_type 'varchar', 'text' alias_type 'char', 'text' alias_type 'bpchar', 'text' @@ -355,13 +363,13 @@ This is not reliable and will be removed in the future. register_type 'date', OID::Date.new register_type 'time', OID::Time.new - register_type 'path', OID::Identity.new + register_type 'path', OID::Text.new register_type 'point', OID::Point.new - register_type 'polygon', OID::Identity.new - register_type 'circle', OID::Identity.new + register_type 'polygon', OID::Text.new + register_type 'circle', OID::Text.new register_type 'hstore', OID::Hstore.new register_type 'json', OID::Json.new - register_type 'ltree', OID::Identity.new + register_type 'ltree', OID::Text.new register_type 'cidr', OID::Cidr.new alias_type 'inet', 'cidr' diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index 6c581a432f..38a43de05a 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -555,6 +555,24 @@ class AttributeMethodsTest < ActiveRecord::TestCase end end + def test_converted_values_are_returned_after_assignment + developer = Developer.new(name: 1337, salary: "50000") + + assert_equal "50000", developer.salary_before_type_cast + assert_equal 1337, developer.name_before_type_cast + + assert_equal 50000, developer.salary + assert_equal "1337", developer.name + + developer.save! + + assert_equal "50000", developer.salary_before_type_cast + assert_equal 1337, developer.name_before_type_cast + + assert_equal 50000, developer.salary + assert_equal "1337", developer.name + end + def test_write_nil_to_time_attributes in_time_zone "Pacific Time (US & Canada)" do record = @target.new -- cgit v1.2.3