From ba29c28a47c8a8016f32cad8b7fcc6dbd0e06162 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Tue, 17 Jun 2014 17:05:34 -0600 Subject: Detect mutations of arrays and array members --- activerecord/CHANGELOG.md | 4 ++++ .../connection_adapters/postgresql/oid/array.rb | 26 ++++++++++++---------- .../test/cases/adapters/postgresql/array_test.rb | 23 +++++++++++++++++++ 3 files changed, 41 insertions(+), 12 deletions(-) (limited to 'activerecord') diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index fc726d6519..823597fc92 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,7 @@ +* Detect in-place modifications of PG array types + + *Sean Griffin* + * Add `bin/rake db:purge` task to empty the current database. *Yves Senn* diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb index 63f3be45de..d322c56acc 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb @@ -3,6 +3,20 @@ module ActiveRecord module PostgreSQL module OID # :nodoc: class Array < Type::Value + include Type::Mutable + + # Loads pg_array_parser if available. String parsing can be + # performed quicker by a native extension, which will not create + # a large amount of Ruby objects that will need to be garbage + # collected. pg_array_parser has a C and Java extension + begin + require 'pg_array_parser' + include PgArrayParser + rescue LoadError + require 'active_record/connection_adapters/postgresql/array_parser' + include PostgreSQL::ArrayParser + end + attr_reader :subtype, :delimiter delegate :type, to: :subtype @@ -31,18 +45,6 @@ module ActiveRecord end end - # Loads pg_array_parser if available. String parsing can be - # performed quicker by a native extension, which will not create - # a large amount of Ruby objects that will need to be garbage - # collected. pg_array_parser has a C and Java extension - begin - require 'pg_array_parser' - include PgArrayParser - rescue LoadError - require 'active_record/connection_adapters/postgresql/array_parser' - include PostgreSQL::ArrayParser - end - private def type_cast_array(value, method) diff --git a/activerecord/test/cases/adapters/postgresql/array_test.rb b/activerecord/test/cases/adapters/postgresql/array_test.rb index 15901b389e..266592e2c7 100644 --- a/activerecord/test/cases/adapters/postgresql/array_test.rb +++ b/activerecord/test/cases/adapters/postgresql/array_test.rb @@ -16,6 +16,7 @@ class PostgresqlArrayTest < ActiveRecord::TestCase t.string 'tags', array: true t.integer 'ratings', array: true t.datetime :datetimes, array: true + t.hstore :hstores, array: true end end @column = PgArray.columns_hash['tags'] @@ -221,6 +222,28 @@ class PostgresqlArrayTest < ActiveRecord::TestCase assert_equal %({hello,;"world;"}), semicolon_delim.type_cast_for_database(strings) end + def test_mutate_array + x = PgArray.create!(tags: %w(one two)) + + x.tags << "three" + x.save! + x.reload + + assert_equal %w(one two three), x.tags + assert_not x.changed? + end + + def test_mutate_value_in_array + x = PgArray.create!(hstores: [{ a: 'a' }, { b: 'b' }]) + + x.hstores.first['a'] = 'c' + x.save! + x.reload + + assert_equal [{ 'a' => 'c' }, { 'b' => 'b' }], x.hstores + assert_not x.changed? + end + def test_datetime_with_timezone_awareness tz = "Pacific Time (US & Canada)" -- cgit v1.2.3