diff options
author | Carlos Antonio da Silva <carlosantoniodasilva@gmail.com> | 2013-12-19 17:39:20 -0200 |
---|---|---|
committer | Carlos Antonio da Silva <carlosantoniodasilva@gmail.com> | 2013-12-23 16:26:15 -0200 |
commit | 56510091fb8d178ec7c2391bed9fbdb9e3a54287 (patch) | |
tree | a4827bf9d0539ce16cfae2497679d3841a64b64d | |
parent | 618d5317d3ce3d40a22293149f79ff9843bbdb35 (diff) | |
download | rails-56510091fb8d178ec7c2391bed9fbdb9e3a54287.tar.gz rails-56510091fb8d178ec7c2391bed9fbdb9e3a54287.tar.bz2 rails-56510091fb8d178ec7c2391bed9fbdb9e3a54287.zip |
Do not consider PG array columns as number or text columns
The code uses these checks in several places to know what to do with a
particular column, for instance AR attribute query methods has a branch
like this:
if column.number?
!value.zero?
end
This should never be true for array columns, since it would be the same
as running [].zero?, which results in a NoMethodError exception.
Fixing this by ensuring that array columns in PostgreSQL never return
true for number?/text? checks.
Since most of the array support was based on the postgres_ext lib, it's
worth noting it does the same thing for numeric array columns too:
https://github.com/dockyard/postgres_ext/blob/v1.0.0/lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb#L72
This extended the same logic for text columns to ensure consistency.
-rw-r--r-- | activerecord/CHANGELOG.md | 18 | ||||
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb | 10 | ||||
-rw-r--r-- | activerecord/test/cases/adapters/postgresql/array_test.rb | 8 |
3 files changed, 33 insertions, 3 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 6d130ab4d6..45dfeddba8 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,21 @@ +* 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 + particular column, for instance AR attribute query methods has a branch + like this: + + if column.number? + !value.zero? + end + + This should never be true for array columns, since it would be the same + as running [].zero?, which results in a NoMethodError exception. + + Fixing this by ensuring that array columns in PostgreSQL never return + true for number?/text? checks. + + *Carlos Antonio da Silva* + * When connecting to a non-existant postgresql database, the error: `ActiveRecord::NoDatabaseError` will now be raised. When being used with Rails the error message will include information on how to create a database: diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 95cd69d5ad..11a5eba464 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -46,7 +46,7 @@ module ActiveRecord # PostgreSQL-specific extensions to column definitions in a table. class PostgreSQLColumn < Column #:nodoc: attr_accessor :array - # Instantiates a new PostgreSQL column definition in a table. + def initialize(name, default, oid_type, sql_type = nil, null = true) @oid_type = oid_type default_value = self.class.extract_value_from_default(default) @@ -62,6 +62,14 @@ module ActiveRecord @default_function = default if has_default_function?(default_value, default) end + def number? + !array && super + end + + def text? + !array && super + end + # :stopdoc: class << self include ConnectionAdapters::PostgreSQLColumn::Cast diff --git a/activerecord/test/cases/adapters/postgresql/array_test.rb b/activerecord/test/cases/adapters/postgresql/array_test.rb index 114d5b6cc6..b0870e2256 100644 --- a/activerecord/test/cases/adapters/postgresql/array_test.rb +++ b/activerecord/test/cases/adapters/postgresql/array_test.rb @@ -26,6 +26,12 @@ class PostgresqlArrayTest < ActiveRecord::TestCase def test_column assert_equal :string, @column.type assert @column.array + assert_not @column.text? + + ratings_column = PgArray.columns_hash['ratings'] + assert_equal :integer, ratings_column.type + assert ratings_column.array + assert_not ratings_column.number? end def test_change_column_with_array @@ -50,8 +56,6 @@ class PostgresqlArrayTest < ActiveRecord::TestCase end def test_type_cast_array - assert @column - data = '{1,2,3}' oid_type = @column.instance_variable_get('@oid_type').subtype # we are getting the instance variable in this test, but in the |