mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #16231 from Envek/type_in_references
* Allow to specify a type for foreign key column in migrations * unified the docs * some cleanup in CHANGELOG
This commit is contained in:
commit
aa3740ebd2
6 changed files with 56 additions and 5 deletions
|
@ -1,3 +1,14 @@
|
|||
* Allow to specify a type for the foreign key column in `references`
|
||||
and `add_reference`.
|
||||
|
||||
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.
|
||||
|
||||
|
|
|
@ -280,12 +280,22 @@ module ActiveRecord
|
|||
column(:updated_at, :datetime, options)
|
||||
end
|
||||
|
||||
# Adds a reference. Optionally adds a +type+ column, if <tt>:polymorphic</tt> option is provided.
|
||||
# <tt>references</tt> and <tt>belongs_to</tt> are acceptable. The reference column will be an +integer+
|
||||
# by default, the <tt>:type</tt> option can be used to specify a different type.
|
||||
#
|
||||
# t.references(:user)
|
||||
# t.references(:user, type: "string")
|
||||
# t.belongs_to(:supplier, polymorphic: true)
|
||||
#
|
||||
# See SchemaStatements#add_reference
|
||||
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
|
||||
|
@ -500,11 +510,14 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
# Adds a reference. Optionally adds a +type+ column, if <tt>:polymorphic</tt> option is provided.
|
||||
# <tt>references</tt> and <tt>belongs_to</tt> are acceptable.
|
||||
# <tt>references</tt> and <tt>belongs_to</tt> are acceptable. The reference column will be an +integer+
|
||||
# by default, the <tt>:type</tt> option can be used to specify a different type.
|
||||
#
|
||||
# t.references(:user)
|
||||
# t.references(:user, type: "string")
|
||||
# t.belongs_to(:supplier, polymorphic: true)
|
||||
#
|
||||
# See SchemaStatements#add_reference
|
||||
def references(*args)
|
||||
options = args.extract_options!
|
||||
args.each do |ref_name|
|
||||
|
@ -519,6 +532,7 @@ module ActiveRecord
|
|||
# t.remove_references(:user)
|
||||
# t.remove_belongs_to(:supplier, polymorphic: true)
|
||||
#
|
||||
# See SchemaStatements#remove_reference
|
||||
def remove_references(*args)
|
||||
options = args.extract_options!
|
||||
args.each do |ref_name|
|
||||
|
|
|
@ -602,12 +602,18 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
# Adds a reference. Optionally adds a +type+ column, if <tt>:polymorphic</tt> option is provided.
|
||||
# The reference column is an +integer+ by default, the <tt>:type</tt> option can be used to specify
|
||||
# a different type.
|
||||
# <tt>add_reference</tt> and <tt>add_belongs_to</tt> are acceptable.
|
||||
#
|
||||
# ====== Create a user_id column
|
||||
# ====== Create a user_id integer column
|
||||
#
|
||||
# add_reference(:products, :user)
|
||||
#
|
||||
# ====== Create a user_id string column
|
||||
#
|
||||
# add_reference(:products, :user, type: :string)
|
||||
#
|
||||
# ====== Create a supplier_id and supplier_type columns
|
||||
#
|
||||
# add_belongs_to(:products, :supplier, polymorphic: true)
|
||||
|
@ -619,7 +625,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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -55,6 +55,11 @@ 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_deletes_reference_id_column
|
||||
remove_reference table_name, :supplier
|
||||
assert_not column_exists?(table_name, :supplier_id, :integer)
|
||||
|
|
Loading…
Reference in a new issue