1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

PG arrays should type cast user input

We guarantee that `model.value` does not change after
`model.save && model.reload`. This requires type casting user input for
non-string types.
This commit is contained in:
Sean Griffin 2014-06-13 07:16:15 -06:00
parent 9a0c2e5c62
commit d569d0baad
2 changed files with 15 additions and 6 deletions

View file

@ -12,12 +12,16 @@ module ActiveRecord
def type_cast_from_database(value) def type_cast_from_database(value)
if value.is_a?(::String) if value.is_a?(::String)
type_cast_array(parse_pg_array(value)) type_cast_array(parse_pg_array(value), :type_cast_from_database)
else else
super super
end end
end end
def type_cast_from_user(value)
type_cast_array(value, :type_cast_from_user)
end
# Loads pg_array_parser if available. String parsing can be # Loads pg_array_parser if available. String parsing can be
# performed quicker by a native extension, which will not create # performed quicker by a native extension, which will not create
# a large amount of Ruby objects that will need to be garbage # a large amount of Ruby objects that will need to be garbage
@ -32,11 +36,11 @@ module ActiveRecord
private private
def type_cast_array(value) def type_cast_array(value, method)
if value.is_a?(::Array) if value.is_a?(::Array)
value.map { |item| type_cast_array(item) } value.map { |item| type_cast_array(item, method) }
else else
@subtype.type_cast_from_database(value) @subtype.public_send(method, value)
end end
end end
end end

View file

@ -97,8 +97,13 @@ class PostgresqlArrayTest < ActiveRecord::TestCase
def test_type_cast_integers def test_type_cast_integers
x = PgArray.new(ratings: ['1', '2']) x = PgArray.new(ratings: ['1', '2'])
assert x.save!
assert_equal(['1', '2'], x.ratings) assert_equal([1, 2], x.ratings)
x.save!
x.reload
assert_equal([1, 2], x.ratings)
end end
def test_select_with_strings def test_select_with_strings