aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/associations.rb6
-rw-r--r--activerecord/lib/active_record/associations/builder/association.rb5
-rw-r--r--activerecord/lib/active_record/associations/preloader/association.rb32
-rw-r--r--activerecord/lib/active_record/associations/preloader/belongs_to.rb7
-rw-r--r--activerecord/lib/active_record/associations/preloader/collection_association.rb11
-rw-r--r--activerecord/lib/active_record/associations/preloader/has_many.rb7
-rw-r--r--activerecord/lib/active_record/associations/preloader/has_one.rb7
-rw-r--r--activerecord/lib/active_record/associations/preloader/singular_association.rb11
-rw-r--r--activerecord/lib/active_record/associations/preloader/through_association.rb1
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/column.rb9
-rw-r--r--activerecord/lib/active_record/migration/compatibility.rb15
-rw-r--r--activerecord/lib/active_record/reflection.rb18
-rw-r--r--activerecord/test/cases/adapters/postgresql/serial_test.rb36
-rw-r--r--activerecord/test/cases/attributes_test.rb2
-rw-r--r--activerecord/test/cases/migration/compatibility_test.rb30
16 files changed, 128 insertions, 71 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index a61c0336db..ef26f4a20c 100644
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1400,7 +1400,7 @@ module ActiveRecord
# has_many :tags, as: :taggable
# has_many :reports, -> { readonly }
# has_many :subscribers, through: :subscriptions, source: :user
- def has_many(name, scope = nil, options = {}, &extension)
+ def has_many(name, scope = nil, **options, &extension)
reflection = Builder::HasMany.build(self, name, scope, options, &extension)
Reflection.add_reflection self, name, reflection
end
@@ -1534,7 +1534,7 @@ module ActiveRecord
# has_one :club, through: :membership
# has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
# has_one :credit_card, required: true
- def has_one(name, scope = nil, options = {})
+ def has_one(name, scope = nil, **options)
reflection = Builder::HasOne.build(self, name, scope, options)
Reflection.add_reflection self, name, reflection
end
@@ -1678,7 +1678,7 @@ module ActiveRecord
# belongs_to :company, touch: :employees_last_updated_at
# belongs_to :user, optional: true
# belongs_to :account, default: -> { company.account }
- def belongs_to(name, scope = nil, options = {})
+ def belongs_to(name, scope = nil, **options)
reflection = Builder::BelongsTo.build(self, name, scope, options)
Reflection.add_reflection self, name, reflection
end
diff --git a/activerecord/lib/active_record/associations/builder/association.rb b/activerecord/lib/active_record/associations/builder/association.rb
index 496b16b58f..ca3032d967 100644
--- a/activerecord/lib/active_record/associations/builder/association.rb
+++ b/activerecord/lib/active_record/associations/builder/association.rb
@@ -38,11 +38,6 @@ module ActiveRecord::Associations::Builder # :nodoc:
def self.create_reflection(model, name, scope, options, extension = nil)
raise ArgumentError, "association names must be a Symbol" unless name.kind_of?(Symbol)
- if scope.is_a?(Hash)
- options = scope
- scope = nil
- end
-
validate_options(options)
scope = build_scope(scope, extension)
diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb
index 9bb6a613e1..fe696e0d6e 100644
--- a/activerecord/lib/active_record/associations/preloader/association.rb
+++ b/activerecord/lib/active_record/associations/preloader/association.rb
@@ -17,26 +17,20 @@ module ActiveRecord
end
def run(preloader)
- preload(preloader)
- end
-
- def preload(preloader)
- raise NotImplementedError
- end
-
- # The name of the key on the associated records
- def association_key_name
- raise NotImplementedError
- end
-
- # The name of the key on the model which declares the association
- def owner_key_name
- raise NotImplementedError
+ associated_records_by_owner(preloader).each do |owner, records|
+ associate_records_to_owner(owner, records)
+ end
end
private
- def options
- reflection.options
+ # The name of the key on the associated records
+ def association_key_name
+ reflection.join_primary_key(klass)
+ end
+
+ # The name of the key on the model which declares the association
+ def owner_key_name
+ reflection.join_foreign_key
end
def associated_records_by_owner(preloader)
@@ -51,6 +45,10 @@ module ActiveRecord
end
end
+ def associate_records_to_owner(owner, records)
+ raise NotImplementedError
+ end
+
def owner_keys
unless defined?(@owner_keys)
@owner_keys = owners.map do |owner|
diff --git a/activerecord/lib/active_record/associations/preloader/belongs_to.rb b/activerecord/lib/active_record/associations/preloader/belongs_to.rb
index ae9695f26a..a8e3340b23 100644
--- a/activerecord/lib/active_record/associations/preloader/belongs_to.rb
+++ b/activerecord/lib/active_record/associations/preloader/belongs_to.rb
@@ -4,13 +4,6 @@ module ActiveRecord
module Associations
class Preloader
class BelongsTo < SingularAssociation #:nodoc:
- def association_key_name
- options[:primary_key] || klass && klass.primary_key
- end
-
- def owner_key_name
- reflection.foreign_key
- end
end
end
end
diff --git a/activerecord/lib/active_record/associations/preloader/collection_association.rb b/activerecord/lib/active_record/associations/preloader/collection_association.rb
index fb920a642c..fc2029f54a 100644
--- a/activerecord/lib/active_record/associations/preloader/collection_association.rb
+++ b/activerecord/lib/active_record/associations/preloader/collection_association.rb
@@ -5,13 +5,10 @@ module ActiveRecord
class Preloader
class CollectionAssociation < Association #:nodoc:
private
-
- def preload(preloader)
- associated_records_by_owner(preloader).each do |owner, records|
- association = owner.association(reflection.name)
- association.loaded!
- association.target.concat(records)
- end
+ def associate_records_to_owner(owner, records)
+ association = owner.association(reflection.name)
+ association.loaded!
+ association.target.concat(records)
end
end
end
diff --git a/activerecord/lib/active_record/associations/preloader/has_many.rb b/activerecord/lib/active_record/associations/preloader/has_many.rb
index 29a1ce099d..72f55bc43f 100644
--- a/activerecord/lib/active_record/associations/preloader/has_many.rb
+++ b/activerecord/lib/active_record/associations/preloader/has_many.rb
@@ -4,13 +4,6 @@ module ActiveRecord
module Associations
class Preloader
class HasMany < CollectionAssociation #:nodoc:
- def association_key_name
- reflection.foreign_key
- end
-
- def owner_key_name
- reflection.active_record_primary_key
- end
end
end
end
diff --git a/activerecord/lib/active_record/associations/preloader/has_one.rb b/activerecord/lib/active_record/associations/preloader/has_one.rb
index d87abf630f..e339b65fb5 100644
--- a/activerecord/lib/active_record/associations/preloader/has_one.rb
+++ b/activerecord/lib/active_record/associations/preloader/has_one.rb
@@ -4,13 +4,6 @@ module ActiveRecord
module Associations
class Preloader
class HasOne < SingularAssociation #:nodoc:
- def association_key_name
- reflection.foreign_key
- end
-
- def owner_key_name
- reflection.active_record_primary_key
- end
end
end
end
diff --git a/activerecord/lib/active_record/associations/preloader/singular_association.rb b/activerecord/lib/active_record/associations/preloader/singular_association.rb
index 266b5f6b1c..30a92411e3 100644
--- a/activerecord/lib/active_record/associations/preloader/singular_association.rb
+++ b/activerecord/lib/active_record/associations/preloader/singular_association.rb
@@ -5,14 +5,9 @@ module ActiveRecord
class Preloader
class SingularAssociation < Association #:nodoc:
private
-
- def preload(preloader)
- associated_records_by_owner(preloader).each do |owner, associated_records|
- record = associated_records.first
-
- association = owner.association(reflection.name)
- association.target = record
- end
+ def associate_records_to_owner(owner, records)
+ association = owner.association(reflection.name)
+ association.target = records.first
end
end
end
diff --git a/activerecord/lib/active_record/associations/preloader/through_association.rb b/activerecord/lib/active_record/associations/preloader/through_association.rb
index 53e9c14823..fa32cc5553 100644
--- a/activerecord/lib/active_record/associations/preloader/through_association.rb
+++ b/activerecord/lib/active_record/associations/preloader/through_association.rb
@@ -80,6 +80,7 @@ module ActiveRecord
def through_scope
scope = through_reflection.klass.unscoped
+ options = reflection.options
if options[:source_type]
scope.where! reflection.foreign_type => options[:source_type]
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 f57c7a5d4d..c9607df28c 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -522,6 +522,8 @@ module ActiveRecord
# Specifies the precision for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
# * <tt>:scale</tt> -
# Specifies the scale for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
+ # * <tt>:comment</tt> -
+ # Specifies the comment for the column. This option is ignored by some backends.
#
# Note: The precision is the total number of significant digits,
# and the scale is the number of digits that can be stored following
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
index 1b67cee24b..ff95fa4a0e 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
@@ -10,8 +10,15 @@ module ActiveRecord
def serial?
return unless default_function
- %r{\Anextval\('"?#{table_name}_#{name}_seq"?'::regclass\)\z} === default_function
+ if %r{\Anextval\('"?(?<sequence_name>.+_(?<suffix>seq\d*))"?'::regclass\)\z} =~ default_function
+ sequence_name_from_parts(table_name, name, suffix) == sequence_name
+ end
end
+
+ private
+ def sequence_name_from_parts(table_name, column_name, suffix)
+ "#{table_name}_#{column_name}_#{suffix}"
+ end
end
end
end
diff --git a/activerecord/lib/active_record/migration/compatibility.rb b/activerecord/lib/active_record/migration/compatibility.rb
index 784292f3f9..87c1c58aff 100644
--- a/activerecord/lib/active_record/migration/compatibility.rb
+++ b/activerecord/lib/active_record/migration/compatibility.rb
@@ -71,6 +71,21 @@ module ActiveRecord
end
end
+ def create_join_table(table_1, table_2, column_options: {}, **options)
+ column_options.reverse_merge!(type: :integer)
+
+ if block_given?
+ super(table_1, table_2, column_options: column_options, **options) do |t|
+ class << t
+ prepend TableDefinition
+ end
+ yield t
+ end
+ else
+ super
+ end
+ end
+
def add_reference(table_name, ref_name, **options)
super(table_name, ref_name, type: :integer, **options)
end
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb
index 889e24dd1a..82ab2415e1 100644
--- a/activerecord/lib/active_record/reflection.rb
+++ b/activerecord/lib/active_record/reflection.rb
@@ -292,13 +292,17 @@ module ActiveRecord
end
def get_join_keys(association_klass)
- JoinKeys.new(join_pk(association_klass), join_foreign_key)
+ JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
end
def build_scope(table, predicate_builder = predicate_builder(table))
Relation.create(klass, table, predicate_builder)
end
+ def join_primary_key(_)
+ foreign_key
+ end
+
def join_foreign_key
active_record_primary_key
end
@@ -313,10 +317,6 @@ module ActiveRecord
PredicateBuilder.new(TableMetadata.new(klass, table))
end
- def join_pk(_)
- foreign_key
- end
-
def primary_key(klass)
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
end
@@ -736,6 +736,10 @@ module ActiveRecord
end
end
+ def join_primary_key(klass)
+ polymorphic? ? association_primary_key(klass) : association_primary_key
+ end
+
def join_foreign_key
foreign_key
end
@@ -745,10 +749,6 @@ module ActiveRecord
def calculate_constructable(macro, options)
!polymorphic?
end
-
- def join_pk(klass)
- polymorphic? ? association_primary_key(klass) : association_primary_key
- end
end
class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
diff --git a/activerecord/test/cases/adapters/postgresql/serial_test.rb b/activerecord/test/cases/adapters/postgresql/serial_test.rb
index 3c020a88d0..df7875dbf2 100644
--- a/activerecord/test/cases/adapters/postgresql/serial_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/serial_test.rb
@@ -86,3 +86,39 @@ class PostgresqlBigSerialTest < ActiveRecord::PostgreSQLTestCase
assert_match %r{t\.bigint\s+"serials_id",\s+default: -> \{ "nextval\('postgresql_big_serials_id_seq'::regclass\)" \}$}, output
end
end
+
+module SequenceNameDetectionTestCases
+ class CollidedSequenceNameTest < ActiveRecord::PostgreSQLTestCase
+ include SchemaDumpingHelper
+
+ def setup
+ @connection = ActiveRecord::Base.connection
+ @connection.create_table :foo_bar, force: true do |t|
+ t.serial :baz_id
+ end
+ @connection.create_table :foo, force: true do |t|
+ t.serial :bar_id
+ t.bigserial :bar_baz_id
+ end
+ end
+
+ def teardown
+ @connection.drop_table :foo_bar, if_exists: true
+ @connection.drop_table :foo, if_exists: true
+ end
+
+ def test_serial_columns
+ columns = @connection.columns(:foo)
+ columns.each do |column|
+ assert_equal :integer, column.type
+ assert column.serial?
+ end
+ end
+
+ def test_schema_dump_with_collided_sequence_name
+ output = dump_table_schema "foo"
+ assert_match %r{t\.serial\s+"bar_id",\s+null: false$}, output
+ assert_match %r{t\.bigserial\s+"bar_baz_id",\s+null: false$}, output
+ end
+ end
+end
diff --git a/activerecord/test/cases/attributes_test.rb b/activerecord/test/cases/attributes_test.rb
index 29a25b4461..2caf2a63d4 100644
--- a/activerecord/test/cases/attributes_test.rb
+++ b/activerecord/test/cases/attributes_test.rb
@@ -108,12 +108,14 @@ module ActiveRecord
assert_equal 6, klass.attribute_types.length
assert_equal 6, klass.column_defaults.length
+ assert_equal 6, klass.attribute_names.length
assert_not klass.attribute_types.include?("wibble")
klass.attribute :wibble, Type::Value.new
assert_equal 7, klass.attribute_types.length
assert_equal 7, klass.column_defaults.length
+ assert_equal 7, klass.attribute_names.length
assert_includes klass.attribute_types, "wibble"
end
diff --git a/activerecord/test/cases/migration/compatibility_test.rb b/activerecord/test/cases/migration/compatibility_test.rb
index cb3b02c02a..e1311c0f21 100644
--- a/activerecord/test/cases/migration/compatibility_test.rb
+++ b/activerecord/test/cases/migration/compatibility_test.rb
@@ -199,6 +199,36 @@ class LegacyPrimaryKeyTest < ActiveRecord::TestCase
assert_match %r{create_table "legacy_primary_keys", id: :integer, default: nil}, schema
end
+ def test_legacy_join_table_foreign_keys_should_be_integer
+ @migration = Class.new(ActiveRecord::Migration[5.0]) {
+ def change
+ create_join_table :apples, :bananas do |t|
+ end
+ end
+ }.new
+
+ @migration.migrate(:up)
+
+ schema = dump_table_schema "apples_bananas"
+ assert_match %r{integer "apple_id", null: false}, schema
+ assert_match %r{integer "banana_id", null: false}, schema
+ end
+
+ def test_legacy_join_table_column_options_should_be_overwritten
+ @migration = Class.new(ActiveRecord::Migration[5.0]) {
+ def change
+ create_join_table :apples, :bananas, column_options: { type: :bigint } do |t|
+ end
+ end
+ }.new
+
+ @migration.migrate(:up)
+
+ schema = dump_table_schema "apples_bananas"
+ assert_match %r{bigint "apple_id", null: false}, schema
+ assert_match %r{bigint "banana_id", null: false}, schema
+ end
+
if current_adapter?(:Mysql2Adapter)
def test_legacy_bigint_primary_key_should_be_auto_incremented
@migration = Class.new(ActiveRecord::Migration[5.0]) {