diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 6d0a2e13ee..5115d4b4d1 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,14 @@ +* Allow to specify a type for created foreign key column in `references` and + `add_reference` in migrations. + + Example: + + change_table :vehicle do |t| + t.references :station, type: :uuid + end + + *Andrey Novikov & Ɓukasz Sarnacki* + * `create_join_table` removes a common prefix when generating the join table. This matches the existing behavior of HABTM associations. diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb index 98e6795f10..d51bf022a4 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb @@ -280,12 +280,19 @@ module ActiveRecord column(:updated_at, :datetime, options) end + # Adds an appropriately-named _id column as :integer (or whatever :type option specifies), + # plus a corresponding _type column if the :polymorphic option is supplied. If :polymorphic + # is a hash of options, these will be used when creating the _type column. The :index option + # will also create an index, similar to calling add_index. + # + # references :tagger, polymorphic: true, index: true, type: :uuid def references(*args) options = args.extract_options! polymorphic = options.delete(:polymorphic) index_options = options.delete(:index) + type = options.delete(:type) || :integer args.each do |col| - column("#{col}_id", :integer, options) + column("#{col}_id", type, options) column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic index(polymorphic ? %w(id type).map { |t| "#{col}_#{t}" } : "#{col}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index 5814c2b711..8ecb7c0506 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -619,7 +619,8 @@ module ActiveRecord def add_reference(table_name, ref_name, options = {}) polymorphic = options.delete(:polymorphic) index_options = options.delete(:index) - add_column(table_name, "#{ref_name}_id", :integer, options) + type = options.delete(:type) || :integer + add_column(table_name, "#{ref_name}_id", type, options) add_column(table_name, "#{ref_name}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic add_index(table_name, polymorphic ? %w[id type].map{ |t| "#{ref_name}_#{t}" } : "#{ref_name}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options end diff --git a/activerecord/test/cases/adapters/postgresql/uuid_test.rb b/activerecord/test/cases/adapters/postgresql/uuid_test.rb index d7ff81a382..66006d718f 100644 --- a/activerecord/test/cases/adapters/postgresql/uuid_test.rb +++ b/activerecord/test/cases/adapters/postgresql/uuid_test.rb @@ -233,7 +233,7 @@ class PostgresqlUUIDTestInverseOf < ActiveRecord::TestCase t.string 'title' end connection.create_table('pg_uuid_comments', id: :uuid) do |t| - t.uuid :uuid_post_id, default: 'uuid_generate_v4()' + t.references :uuid_post, type: :uuid t.string 'content' end end diff --git a/activerecord/test/cases/migration/change_table_test.rb b/activerecord/test/cases/migration/change_table_test.rb index a6d506b04a..3e9d957ed3 100644 --- a/activerecord/test/cases/migration/change_table_test.rb +++ b/activerecord/test/cases/migration/change_table_test.rb @@ -72,6 +72,20 @@ module ActiveRecord end end + def test_references_column_type_with_polymorphic_and_type + with_change_table do |t| + @connection.expect :add_reference, nil, [:delete_me, :taggable, polymorphic: true, type: :string] + t.references :taggable, polymorphic: true, type: :string + end + end + + def test_remove_references_column_type_with_polymorphic_and_type + with_change_table do |t| + @connection.expect :remove_reference, nil, [:delete_me, :taggable, polymorphic: true, type: :string] + t.remove_references :taggable, polymorphic: true, type: :string + end + end + def test_timestamps_creates_updated_at_and_created_at with_change_table do |t| @connection.expect :add_timestamps, nil, [:delete_me] diff --git a/activerecord/test/cases/migration/references_statements_test.rb b/activerecord/test/cases/migration/references_statements_test.rb index e9545f2cce..1fdfbdd181 100644 --- a/activerecord/test/cases/migration/references_statements_test.rb +++ b/activerecord/test/cases/migration/references_statements_test.rb @@ -55,6 +55,16 @@ module ActiveRecord assert index_exists?(table_name, :tag_id, name: 'index_taggings_on_tag_id') end + def test_creates_reference_id_with_specified_type + add_reference table_name, :user, type: :string + assert column_exists?(table_name, :user_id, :string) + end + + def test_does_not_create_reference_id_with_specified_type + add_reference table_name, :user + assert_not column_exists?(table_name, :user_id, :string) + end + def test_deletes_reference_id_column remove_reference table_name, :supplier assert_not column_exists?(table_name, :supplier_id, :integer)