From 806bc2add8a0807ca45fb0945856bec89a321fc8 Mon Sep 17 00:00:00 2001 From: Yves Senn Date: Wed, 7 Aug 2013 18:21:45 +0200 Subject: [PATCH] Fix multidimensional PG arrays containing non-string items --- activerecord/CHANGELOG.md | 4 +++ .../connection_adapters/postgresql/cast.rb | 10 +++++- .../cases/adapters/postgresql/array_test.rb | 33 +++++++++++-------- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index f44f98cdec699..487352fce60d5 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,7 @@ +* Fix multidimensional PG arrays containing non-string items. + + *Yves Senn* + * Load fixtures from linked folders. *Kassio Borges* diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb b/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb index a73f0ac57fea4..56dc9ea813e45 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb @@ -115,7 +115,7 @@ def cidr_to_string(object) end def string_to_array(string, oid) - parse_pg_array(string).map{|val| oid.type_cast val} + parse_pg_array(string).map {|val| type_cast_array(oid, val)} end private @@ -146,6 +146,14 @@ def quote_and_escape(value) "\"#{value.gsub(/"/,"\\\"")}\"" end end + + def type_cast_array(oid, value) + if ::Array === value + value.map {|item| type_cast_array(oid, item)} + else + oid.type_cast value + end + end end end end diff --git a/activerecord/test/cases/adapters/postgresql/array_test.rb b/activerecord/test/cases/adapters/postgresql/array_test.rb index c537b08c3eebc..ecdbefcd030eb 100644 --- a/activerecord/test/cases/adapters/postgresql/array_test.rb +++ b/activerecord/test/cases/adapters/postgresql/array_test.rb @@ -12,7 +12,8 @@ def setup @connection = ActiveRecord::Base.connection @connection.transaction do @connection.create_table('pg_arrays') do |t| - t.string 'tags', :array => true + t.string 'tags', array: true + t.integer 'ratings', array: true end end @column = PgArray.columns.find { |c| c.name == 'tags' } @@ -78,28 +79,32 @@ def test_select assert_equal(['1','2','3'], x.tags) end - def test_multi_dimensional - assert_cycle([['1','2'],['2','3']]) + def test_multi_dimensional_with_strings + assert_cycle(:tags, [[['1'], ['2']], [['2'], ['3']]]) + end + + def test_multi_dimensional_with_integers + assert_cycle(:ratings, [[[1], [7]], [[8], [10]]]) end def test_strings_with_quotes - assert_cycle(['this has','some "s that need to be escaped"']) + assert_cycle(:tags, ['this has','some "s that need to be escaped"']) end def test_strings_with_commas - assert_cycle(['this,has','many,values']) + assert_cycle(:tags, ['this,has','many,values']) end def test_strings_with_array_delimiters - assert_cycle(['{','}']) + assert_cycle(:tags, ['{','}']) end def test_strings_with_null_strings - assert_cycle(['NULL','NULL']) + assert_cycle(:tags, ['NULL','NULL']) end def test_contains_nils - assert_cycle(['1',nil,nil]) + assert_cycle(:tags, ['1',nil,nil]) end def test_insert_fixture @@ -109,17 +114,17 @@ def test_insert_fixture end private - def assert_cycle array + def assert_cycle field, array # test creation - x = PgArray.create!(:tags => array) + x = PgArray.create!(field => array) x.reload - assert_equal(array, x.tags) + assert_equal(array, x.public_send(field)) # test updating - x = PgArray.create!(:tags => []) - x.tags = array + x = PgArray.create!(field => []) + x.public_send("#{field}=", array) x.save! x.reload - assert_equal(array, x.tags) + assert_equal(array, x.public_send(field)) end end