From 776af48acb1035e70a326609ec5e5b632ef0c2c5 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 19 Dec 2011 21:16:23 -0800 Subject: [PATCH] PostgreSQL hstore types are automatically deserialized from the database. --- activerecord/CHANGELOG.md | 4 ++++ .../active_record/connection_adapters/column.rb | 2 ++ .../connection_adapters/postgresql_adapter.rb | 4 ++++ .../cases/adapters/postgresql/hstore_test.rb | 16 ++++++++++++++++ 4 files changed, 26 insertions(+) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 348873d7597b1..6ea8ce129a375 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,7 @@ +## Rails 4.0.0 (unreleased) ## + +* PostgreSQL hstore types are automatically deserialized from the database. + ## Rails 3.2.0 (unreleased) ## * Added ability to run migrations only for given scope, which allows diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index 0214154c51c9f..6aa4a2c5b38f2 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -83,6 +83,7 @@ def type_cast(value) when :date then klass.value_to_date(value) when :binary then klass.binary_to_string(value) when :boolean then klass.value_to_boolean(value) + when :hstore then klass.cast_hstore(value) else value end end @@ -100,6 +101,7 @@ def type_cast_code(var_name) when :date then "#{klass}.value_to_date(#{var_name})" when :binary then "#{klass}.binary_to_string(#{var_name})" when :boolean then "#{klass}.value_to_boolean(#{var_name})" + when :hstore then "#{klass}.cast_hstore(#{var_name})" else var_name end end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 9802bac87b631..563f98dc5e9b1 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -49,6 +49,10 @@ def string_to_time(string) super end end + + def cast_hstore(string) + Hash[[string.split('=>').map { |k| k[1...-1] }]] + end end # :startdoc: diff --git a/activerecord/test/cases/adapters/postgresql/hstore_test.rb b/activerecord/test/cases/adapters/postgresql/hstore_test.rb index 155c6f593bb2c..aa3bde09d8294 100644 --- a/activerecord/test/cases/adapters/postgresql/hstore_test.rb +++ b/activerecord/test/cases/adapters/postgresql/hstore_test.rb @@ -21,4 +21,20 @@ def test_column assert column assert_equal :hstore, column.type end + + def test_type_cast_hstore + column = Hstore.columns.find { |c| c.name == 'tags' } + assert column + + data = "\"1\"=>\"2\"" + hash = column.class.cast_hstore data + assert_equal({'1' => '2'}, hash) + assert_equal({'1' => '2'}, column.type_cast(data)) + end + + def test_select + @connection.execute "insert into hstores (tags) VALUES ('1=>2')" + x = Hstore.find :first + assert_equal({'1' => '2'}, x.tags) + end end