aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG.md7
-rw-r--r--activerecord/lib/active_record/sanitization.rb9
-rw-r--r--activerecord/test/cases/adapters/postgresql/array_test.rb6
-rw-r--r--activerecord/test/cases/adapters/postgresql/hstore_test.rb6
-rw-r--r--activerecord/test/cases/adapters/postgresql/json_test.rb6
5 files changed, 30 insertions, 4 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 45dfeddba8..3521e3a9ab 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,10 @@
+* Fixed `update_column`, `update_columns`, and `update_all` to correctly serialize
+ values for `array`, `hstore` and `json` column types in `PostgreSQL`.
+
+ Fixes #12261.
+
+ *Tadas Tamosauskas*
+
* Do not consider PostgreSQL array columns as number or text columns.
The code uses these checks in several places to know what to do with a
diff --git a/activerecord/lib/active_record/sanitization.rb b/activerecord/lib/active_record/sanitization.rb
index cab8fd745a..bc78c3858a 100644
--- a/activerecord/lib/active_record/sanitization.rb
+++ b/activerecord/lib/active_record/sanitization.rb
@@ -101,7 +101,7 @@ module ActiveRecord
# # => "status = NULL , group_id = 1"
def sanitize_sql_hash_for_assignment(attrs, table)
attrs.map do |attr, value|
- "#{connection.quote_table_name_for_assignment(table, attr)} = #{quote_bound_value(value)}"
+ "#{connection.quote_table_name_for_assignment(table, attr)} = #{quote_bound_value(value, connection, columns_hash[attr.to_s])}"
end.join(', ')
end
@@ -152,15 +152,16 @@ module ActiveRecord
end
end
- def quote_bound_value(value, c = connection) #:nodoc:
- if value.respond_to?(:map) && !value.acts_like?(:string)
+ def quote_bound_value(value, c = connection, column = nil) #:nodoc:
+ db_native_type = column && (column.respond_to?(:array) && column.array || [:json, :hstore].include?(column.type) )
+ if value.respond_to?(:map) && !value.acts_like?(:string) && !db_native_type
if value.respond_to?(:empty?) && value.empty?
c.quote(nil)
else
value.map { |v| c.quote(v) }.join(',')
end
else
- c.quote(value)
+ c.quote(value, column)
end
end
diff --git a/activerecord/test/cases/adapters/postgresql/array_test.rb b/activerecord/test/cases/adapters/postgresql/array_test.rb
index b0870e2256..cf059d20e2 100644
--- a/activerecord/test/cases/adapters/postgresql/array_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/array_test.rb
@@ -128,6 +128,12 @@ class PostgresqlArrayTest < ActiveRecord::TestCase
assert_equal("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...]", record.attribute_for_inspect(:ratings))
end
+ def test_update_all
+ PgArray.create! tags: ["one", "two", "three"]
+ PgArray.update_all tags: ["four", "five"]
+ assert_equal ["four", "five"], PgArray.first.tags
+ end
+
private
def assert_cycle field, array
# test creation
diff --git a/activerecord/test/cases/adapters/postgresql/hstore_test.rb b/activerecord/test/cases/adapters/postgresql/hstore_test.rb
index 2845413575..730020b5c8 100644
--- a/activerecord/test/cases/adapters/postgresql/hstore_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/hstore_test.rb
@@ -206,6 +206,12 @@ class PostgresqlHstoreTest < ActiveRecord::TestCase
def test_multiline
assert_cycle("a\nb" => "c\nd")
end
+
+ def test_update_all
+ Hstore.create! tags: { "one" => "two" }
+ Hstore.update_all tags: { "three" => "four" }
+ assert_equal({ "three" => "four" }, Hstore.first.tags)
+ end
end
private
diff --git a/activerecord/test/cases/adapters/postgresql/json_test.rb b/activerecord/test/cases/adapters/postgresql/json_test.rb
index c33c7ef968..10efa8b802 100644
--- a/activerecord/test/cases/adapters/postgresql/json_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/json_test.rb
@@ -121,4 +121,10 @@ class PostgresqlJSONTest < ActiveRecord::TestCase
x = JsonDataType.first
assert_equal "640×1136", x.resolution
end
+
+ def test_update_all
+ JsonDataType.create! payload: { "one" => "two" }
+ JsonDataType.update_all payload: { "three" => "four" }
+ assert_equal({ "three" => "four" }, JsonDataType.first.payload)
+ end
end