mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Attempt to maintain encoding for arrays of strings with PG
I still think that this is something that should be handled in the pg gem, but it's not going to end up happening there so we'll do it here instead. Once we bump to pg 0.19 we can pass the encoding to the `encode` method instead. This issue occurs because C has no concept of encoding (or strings, really). The bytes that we pass here when sending the value to the database will always be interpreted as whatever encoding the connection is currently configured to use. That means that roundtripping to the database will lose no information However, after assigning we round trip through our type system without hitting the database. The only way that we can do the "correct" thin here would be to actually give a reference to the connection to the array type and have it check the current value of the connection's encoding -- which I'm strongly opposed to. We could also pass in the encoding when it's constructed, but since that can change independently of the type I'm not a huge fan of that either. This feels like a reasonable middle ground, where if we have an array of strings we simply use the encoding of the string we're given. Fixes #26326.
This commit is contained in:
parent
03d3f036a7
commit
7ba3a48df5
3 changed files with 25 additions and 1 deletions
|
@ -1,3 +1,10 @@
|
|||
* PostgreSQL array columns will now respect the encoding of strings contained
|
||||
in the array.
|
||||
|
||||
Fixes #26326.
|
||||
|
||||
*Sean Griffin*
|
||||
|
||||
* Inverse association instances will now be set before `after_find` or
|
||||
`after_initialize` callbacks are run.
|
||||
|
||||
|
|
|
@ -33,7 +33,11 @@ module ActiveRecord
|
|||
|
||||
def serialize(value)
|
||||
if value.is_a?(::Array)
|
||||
@pg_encoder.encode(type_cast_array(value, :serialize))
|
||||
result = @pg_encoder.encode(type_cast_array(value, :serialize))
|
||||
if encoding = determine_encoding_of_strings(value)
|
||||
result.encode!(encoding)
|
||||
end
|
||||
result
|
||||
else
|
||||
super
|
||||
end
|
||||
|
@ -63,6 +67,13 @@ module ActiveRecord
|
|||
@subtype.public_send(method, value)
|
||||
end
|
||||
end
|
||||
|
||||
def determine_encoding_of_strings(value)
|
||||
case value
|
||||
when ::Array then determine_encoding_of_strings(value.first)
|
||||
when ::String then value.encoding
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -311,6 +311,12 @@ class PostgresqlArrayTest < ActiveRecord::PostgreSQLTestCase
|
|||
assert_equal ["has already been taken"], e2.errors[:tags], "Should have uniqueness message for tags"
|
||||
end
|
||||
|
||||
def test_encoding_arrays_of_utf8_strings
|
||||
string_with_utf8 = "nový"
|
||||
assert_equal [string_with_utf8], @type.deserialize(@type.serialize([string_with_utf8]))
|
||||
assert_equal [[string_with_utf8]], @type.deserialize(@type.serialize([[string_with_utf8]]))
|
||||
end
|
||||
|
||||
private
|
||||
def assert_cycle(field, array)
|
||||
# test creation
|
||||
|
|
Loading…
Reference in a new issue