class PostgresqlArrayTest

Public Class Methods

model_name() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 348
def self.model_name; ActiveModel::Name.new(PgArray) end

Public Instance Methods

setup() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 14
def setup
  @connection = ActiveRecord::Base.connection

  enable_extension!("hstore", @connection)

  @connection.transaction do
    @connection.create_table("pg_arrays") do |t|
      t.string "tags", array: true, limit: 255
      t.integer "ratings", array: true
      t.datetime :datetimes, array: true
      t.hstore :hstores, array: true
      t.decimal :decimals, array: true, default: [], precision: 10, scale: 2
      t.timestamp :timestamps, array: true, default: [], precision: 6
    end
  end
  PgArray.reset_column_information
  @column = PgArray.columns_hash["tags"]
  @type = PgArray.type_for_attribute("tags")
end
test_array_with_serialized_attributes() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 66
def test_array_with_serialized_attributes
  new_klass = Class.new(PgArray) do
    serialize :tags, MyTags
  end

  new_klass.create!(tags: MyTags.new(["one", "two"]))
  record = new_klass.first

  assert_instance_of MyTags, record.tags
  assert_equal ["one", "two"], record.tags.to_a

  record.tags = MyTags.new(["three", "four"])
  record.save!

  assert_equal ["three", "four"], record.reload.tags.to_a
end
test_assigning_empty_string() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 322
def test_assigning_empty_string
  record = PgArray.new(tags: "")
  assert_equal [], record.tags
  assert_equal "", record.tags_before_type_cast
  assert record.save
  assert_equal record.tags, record.reload.tags
end
test_assigning_non_array_value() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 314
def test_assigning_non_array_value
  record = PgArray.new(tags: "not-an-array")
  assert_equal [], record.tags
  assert_equal "not-an-array", record.tags_before_type_cast
  assert record.save
  assert_equal record.tags, record.reload.tags
end
test_assigning_valid_pg_array_literal() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 330
def test_assigning_valid_pg_array_literal
  record = PgArray.new(tags: "{1,2,3}")
  assert_equal ["1", "2", "3"], record.tags
  assert_equal "{1,2,3}", record.tags_before_type_cast
  assert record.save
  assert_equal record.tags, record.reload.tags
end
test_attribute_for_inspect_for_array_field() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 235
def test_attribute_for_inspect_for_array_field
  record = PgArray.new { |a| a.ratings = (1..10).to_a }
  assert_equal("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", record.attribute_for_inspect(:ratings))
end
test_attribute_for_inspect_for_array_field_for_large_array() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 240
def test_attribute_for_inspect_for_array_field_for_large_array
  record = PgArray.new { |a| a.ratings = (1..11).to_a }
  assert_equal("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]", record.attribute_for_inspect(:ratings))
end
test_change_column_cant_make_non_array_column_to_array() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 115
def test_change_column_cant_make_non_array_column_to_array
  @connection.add_column :pg_arrays, :a_string, :string
  assert_raises ActiveRecord::StatementInvalid do
    @connection.transaction do
      @connection.change_column :pg_arrays, :a_string, :string, array: true
    end
  end
end
test_change_column_default_with_array() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 124
def test_change_column_default_with_array
  @connection.change_column_default :pg_arrays, :tags, []

  PgArray.reset_column_information
  assert_equal [], PgArray.column_defaults["tags"]
end
test_change_column_with_array() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 103
def test_change_column_with_array
  @connection.add_column :pg_arrays, :snippets, :string, array: true, default: []
  @connection.change_column :pg_arrays, :snippets, :text, array: true, default: []

  PgArray.reset_column_information
  column = PgArray.columns_hash["snippets"]

  assert_equal :text, column.type
  assert_equal [], PgArray.column_defaults["snippets"]
  assert column.array?
end
test_column() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 39
def test_column
  assert_equal :string, @column.type
  assert_equal "character varying(255)", @column.sql_type
  assert @column.array?
  assert_not @type.binary?

  ratings_column = PgArray.columns_hash["ratings"]
  assert_equal :integer, ratings_column.type
  assert ratings_column.array?
end
test_contains_nils() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 219
def test_contains_nils
  assert_cycle(:tags, ["1", nil, nil])
end
test_datetime_with_timezone_awareness() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 294
def test_datetime_with_timezone_awareness
  tz = "Pacific Time (US & Canada)"

  in_time_zone tz do
    PgArray.reset_column_information
    time_string = Time.current.to_s
    time = Time.zone.parse(time_string)

    record = PgArray.new(datetimes: [time_string])
    assert_equal [time], record.datetimes
    assert_equal ActiveSupport::TimeZone[tz], record.datetimes.first.time_zone

    record.save!
    record.reload

    assert_equal [time], record.datetimes
    assert_equal ActiveSupport::TimeZone[tz], record.datetimes.first.time_zone
  end
end
test_default() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 83
def test_default
  @connection.add_column "pg_arrays", "score", :integer, array: true, default: [4, 4, 2]
  PgArray.reset_column_information

  assert_equal([4, 4, 2], PgArray.column_defaults["score"])
  assert_equal([4, 4, 2], PgArray.new.score)
ensure
  PgArray.reset_column_information
end
test_default_strings() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 93
def test_default_strings
  @connection.add_column "pg_arrays", "names", :string, array: true, default: ["foo", "bar"]
  PgArray.reset_column_information

  assert_equal(["foo", "bar"], PgArray.column_defaults["names"])
  assert_equal(["foo", "bar"], PgArray.new.names)
ensure
  PgArray.reset_column_information
end
test_encoding_arrays_of_utf8_strings() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 359
def test_encoding_arrays_of_utf8_strings
  arrays_of_utf8_strings = %w(nový ファイル)
  assert_equal arrays_of_utf8_strings, @type.deserialize(@type.serialize(arrays_of_utf8_strings))
  assert_equal [arrays_of_utf8_strings], @type.deserialize(@type.serialize([arrays_of_utf8_strings]))
end
test_escaping() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 245
def test_escaping
  unknown = 'foo\\",bar,baz,\\'
  tags = ["hello_#{unknown}"]
  ar = PgArray.create!(tags: tags)
  ar.reload
  assert_equal tags, ar.tags
end
test_insert_fixture() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 223
def test_insert_fixture
  tag_values = ["val1", "val2", "val3_with_'_multiple_quote_'_chars"]
  @connection.insert_fixture({ "tags" => tag_values }, "pg_arrays")
  assert_equal(PgArray.last.tags, tag_values)
end
test_insert_fixtures() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 229
def test_insert_fixtures
  tag_values = ["val1", "val2", "val3_with_'_multiple_quote_'_chars"]
  @connection.insert_fixtures([{ "tags" => tag_values }], "pg_arrays")
  assert_equal(PgArray.last.tags, tag_values)
end
test_multi_dimensional_with_integers() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 199
def test_multi_dimensional_with_integers
  assert_cycle(:ratings, [[[1], [7]], [[8], [10]]])
end
test_multi_dimensional_with_strings() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 183
def test_multi_dimensional_with_strings
  assert_cycle(:tags, [[["1"], ["2"]], [["2"], ["3"]]])
end
test_mutate_array() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 272
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
test_mutate_value_in_array() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 283
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
test_not_compatible_with_serialize_array() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 50
def test_not_compatible_with_serialize_array
  new_klass = Class.new(PgArray) do
    serialize :tags, Array
  end
  assert_raises(ActiveRecord::AttributeMethods::Serialization::ColumnNotSerializableError) do
    new_klass.new
  end
end
test_precision_is_respected_on_timestamp_columns() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 365
def test_precision_is_respected_on_timestamp_columns
  time = Time.now.change(usec: 123)
  record = PgArray.create!(timestamps: [time])

  assert_equal 123, record.timestamps.first.usec
  record.reload
  assert_equal 123, record.timestamps.first.usec
end
test_quoting_non_standard_delimiters() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 261
def test_quoting_non_standard_delimiters
  strings = ["hello,", "world;"]
  oid = ActiveRecord::ConnectionAdapters::PostgreSQL::OID
  comma_delim = oid::Array.new(ActiveRecord::Type::String.new, ",")
  semicolon_delim = oid::Array.new(ActiveRecord::Type::String.new, ";")
  conn = PgArray.connection

  assert_equal %({"hello,",world;}), conn.type_cast(comma_delim.serialize(strings))
  assert_equal %({hello,;"world;"}), conn.type_cast(semicolon_delim.serialize(strings))
end
test_rewrite_with_integers() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 175
def test_rewrite_with_integers
  @connection.execute "insert into pg_arrays (ratings) VALUES ('{1,2,3}')"
  x = PgArray.first
  x.ratings = [2, "3", 4]
  x.save!
  assert_equal [2, 3, 4], x.reload.ratings
end
test_rewrite_with_strings() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 161
def test_rewrite_with_strings
  @connection.execute "insert into pg_arrays (tags) VALUES ('{1,2,3}')"
  x = PgArray.first
  x.tags = ["1", "2", "3", "4"]
  x.save!
  assert_equal ["1", "2", "3", "4"], x.reload.tags
end
test_schema_dump_with_shorthand() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 148
def test_schema_dump_with_shorthand
  output = dump_table_schema "pg_arrays"
  assert_match %r[t\.string\s+"tags",\s+limit: 255,\s+array: true], output
  assert_match %r[t\.integer\s+"ratings",\s+array: true], output
  assert_match %r[t\.decimal\s+"decimals",\s+precision: 10,\s+scale: 2,\s+default: \[\],\s+array: true], output
end
test_select_with_integers() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 169
def test_select_with_integers
  @connection.execute "insert into pg_arrays (ratings) VALUES ('{1,2,3}')"
  x = PgArray.first
  assert_equal([1, 2, 3], x.ratings)
end
test_select_with_strings() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 155
def test_select_with_strings
  @connection.execute "insert into pg_arrays (tags) VALUES ('{1,2,3}')"
  x = PgArray.first
  assert_equal(["1", "2", "3"], x.tags)
end
test_string_quoting_rules_match_pg_behavior() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 253
def test_string_quoting_rules_match_pg_behavior
  tags = ["", "one{", "two}", %(three"), "four\\", "five ", "six\t", "seven\n", "eight,", "nine", "ten\r", "NULL"]
  x = PgArray.create!(tags: tags)
  x.reload

  refute x.changed?
end
test_strings_with_array_delimiters() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 211
def test_strings_with_array_delimiters
  assert_cycle(:tags, ["{", "}"])
end
test_strings_with_commas() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 207
def test_strings_with_commas
  assert_cycle(:tags, ["this,has", "many,values"])
end
test_strings_with_null_strings() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 215
def test_strings_with_null_strings
  assert_cycle(:tags, ["NULL", "NULL"])
end
test_strings_with_quotes() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 203
def test_strings_with_quotes
  assert_cycle(:tags, ["this has", 'some "s that need to be escaped"'])
end
test_type_cast_array() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 131
def test_type_cast_array
  assert_equal(["1", "2", "3"], @type.deserialize("{1,2,3}"))
  assert_equal([], @type.deserialize("{}"))
  assert_equal([nil], @type.deserialize("{NULL}"))
end
test_type_cast_integers() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 137
def test_type_cast_integers
  x = PgArray.new(ratings: ["1", "2"])

  assert_equal([1, 2], x.ratings)

  x.save!
  x.reload

  assert_equal([1, 2], x.ratings)
end
test_uniqueness_validation() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 344
def test_uniqueness_validation
  klass = Class.new(PgArray) do
    validates_uniqueness_of :tags

    def self.model_name; ActiveModel::Name.new(PgArray) end
  end
  e1 = klass.create("tags" => ["black", "blue"])
  assert e1.persisted?, "Saving e1"

  e2 = klass.create("tags" => ["black", "blue"])
  assert !e2.persisted?, "e2 shouldn't be valid"
  assert e2.errors[:tags].any?, "Should have errors for tags"
  assert_equal ["has already been taken"], e2.errors[:tags], "Should have uniqueness message for tags"
end
test_where_by_attribute_with_array() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 338
def test_where_by_attribute_with_array
  tags = ["black", "blue"]
  record = PgArray.create!(tags: tags)
  assert_equal record, PgArray.where(tags: tags).take
end
test_with_arbitrary_whitespace() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 195
def test_with_arbitrary_whitespace
  assert_cycle(:tags, [[["1", "2"], ["    ", "4"], ["    ", "5"]]])
end
test_with_empty_strings() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 187
def test_with_empty_strings
  assert_cycle(:tags, [ "1", "2", "", "4", "", "5" ])
end
test_with_multi_dimensional_empty_strings() click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 191
def test_with_multi_dimensional_empty_strings
  assert_cycle(:tags, [[["1", "2"], ["", "4"], ["", "5"]]])
end

Private Instance Methods

assert_cycle(field, array) click to toggle source
# File activerecord/test/cases/adapters/postgresql/array_test.rb, line 375
def assert_cycle(field, array)
  # test creation
  x = PgArray.create!(field => array)
  x.reload
  assert_equal(array, x.public_send(field))

  # test updating
  x = PgArray.create!(field => [])
  x.public_send("#{field}=", array)
  x.save!
  x.reload
  assert_equal(array, x.public_send(field))
end