Skip to content
This repository
Browse code

Support PostgreSQL specific column types when using `change_table`.

Closes #9480.

We use `TableDefinition` for `#create_table` and `Table` for `#change_table`.
The PostgreSQL sepcifc types were only defined on `TableDefinition` so I
also added them to `Table`.
  • Loading branch information...
commit 5d0ca7462255b7d52a007cfe5bbc7e1bf67c3f79 1 parent 36abb55
Yves Senn senny authored
12 activerecord/CHANGELOG.md
Source Rendered
... ... @@ -1,5 +1,17 @@
1 1 ## Rails 4.0.0 (unreleased) ##
2 2
  3 +* Support PostgreSQL specific column types when using `change_table`.
  4 + Fixes #9480.
  5 +
  6 + Example:
  7 +
  8 + change_table :authors do |t|
  9 + t.hstore :books
  10 + t.json :metadata
  11 + end
  12 +
  13 + *Yves Senn*
  14 +
3 15 * Revert 408227d9c5ed7d, 'quote numeric'. This introduced some regressions.
4 16
5 17 *Steve Klabnik*
12 activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -156,7 +156,7 @@ def column_exists?(table_name, column_name, type = nil, options = {})
156 156 #
157 157 # See also TableDefinition#column for details on how to create columns.
158 158 def create_table(table_name, options = {})
159   - td = table_definition
  159 + td = create_table_definition
160 160 td.primary_key(options[:primary_key] || Base.get_primary_key(table_name.to_s.singularize)) unless options[:id] == false
161 161
162 162 yield td if block_given?
@@ -298,10 +298,10 @@ def drop_join_table(table_1, table_2, options = {})
298 298 def change_table(table_name, options = {})
299 299 if supports_bulk_alter? && options[:bulk]
300 300 recorder = ActiveRecord::Migration::CommandRecorder.new(self)
301   - yield Table.new(table_name, recorder)
  301 + yield update_table_definition(table_name, recorder)
302 302 bulk_change_table(table_name, recorder.commands)
303 303 else
304   - yield Table.new(table_name, self)
  304 + yield update_table_definition(table_name, self)
305 305 end
306 306 end
307 307
@@ -727,9 +727,13 @@ def rename_column_indexes(table_name, column_name, new_column_name)
727 727 end
728 728
729 729 private
730   - def table_definition
  730 + def create_table_definition
731 731 TableDefinition.new(self)
732 732 end
  733 +
  734 + def update_table_definition(table_name, base)
  735 + Table.new(table_name, base)
  736 + end
733 737 end
734 738 end
735 739 end
16 activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -263,7 +263,7 @@ class ColumnDefinition < ActiveRecord::ConnectionAdapters::ColumnDefinition
263 263 attr_accessor :array
264 264 end
265 265
266   - class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
  266 + module ColumnMethods
267 267 def xml(*args)
268 268 options = args.extract_options!
269 269 column(args[0], 'xml', options)
@@ -325,6 +325,10 @@ def uuid(name, options = {})
325 325 def json(name, options = {})
326 326 column(name, 'json', options)
327 327 end
  328 + end
  329 +
  330 + class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
  331 + include ColumnMethods
328 332
329 333 def column(name, type = nil, options = {})
330 334 super
@@ -344,6 +348,10 @@ def new_column_definition(base, name, type)
344 348 end
345 349 end
346 350
  351 + class Table < ActiveRecord::ConnectionAdapters::Table
  352 + include ColumnMethods
  353 + end
  354 +
347 355 ADAPTER_NAME = 'PostgreSQL'
348 356
349 357 NATIVE_DATABASE_TYPES = {
@@ -884,9 +892,13 @@ def extract_table_ref_from_insert_sql(sql)
884 892 $1.strip if $1
885 893 end
886 894
887   - def table_definition
  895 + def create_table_definition
888 896 TableDefinition.new(self)
889 897 end
  898 +
  899 + def update_table_definition(table_name, base)
  900 + Table.new(table_name, base)
  901 + end
890 902 end
891 903 end
892 904 end
15 activerecord/test/cases/adapters/postgresql/hstore_test.rb
@@ -65,6 +65,21 @@ def test_column
65 65 assert_equal :hstore, @column.type
66 66 end
67 67
  68 + def test_change_table_supports_hstore
  69 + @connection.transaction do
  70 + @connection.change_table('hstores') do |t|
  71 + t.hstore 'users', default: ''
  72 + end
  73 + Hstore.reset_column_information
  74 + column = Hstore.columns.find { |c| c.name == 'users' }
  75 + assert_equal :hstore, column.type
  76 +
  77 + raise ActiveRecord::Rollback # reset the schema change
  78 + end
  79 + ensure
  80 + Hstore.reset_column_information
  81 + end
  82 +
68 83 def test_type_cast_hstore
69 84 assert @column
70 85
15 activerecord/test/cases/adapters/postgresql/json_test.rb
@@ -31,6 +31,21 @@ def test_column
31 31 assert_equal :json, @column.type
32 32 end
33 33
  34 + def test_change_table_supports_json
  35 + @connection.transaction do
  36 + @connection.change_table('json_data_type') do |t|
  37 + t.json 'users', default: '{}'
  38 + end
  39 + JsonDataType.reset_column_information
  40 + column = JsonDataType.columns.find { |c| c.name == 'users' }
  41 + assert_equal :json, column.type
  42 +
  43 + raise ActiveRecord::Rollback # reset the schema change
  44 + end
  45 + ensure
  46 + JsonDataType.reset_column_information
  47 + end
  48 +
34 49 def test_type_cast_json
35 50 assert @column
36 51

0 comments on commit 5d0ca74

Please sign in to comment.
Something went wrong with that request. Please try again.