diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 44ddbbcf77..956d43de1c 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,21 @@ +* Allow composite primary key to be derived from schema + + Booting an application with a schema that contains composite primary keys + will not issue warning and won't `nil`ify the `ActiveRecord::Base#primary_key` value anymore. + + Given a `travel_routes` table definition and a `TravelRoute` model like: + ```ruby + create_table :travel_routes, primary_key: [:origin, :destination], force: true do |t| + t.string :origin + t.string :destination + end + + class TravelRoute < ActiveRecord::Base; end + ``` + The `TravelRoute.primary_key` value will be automatically derived to `["origin", "destination"]` + + *Nikita Vasilevsky* + * Include the `connection_pool` with exceptions raised from an adapter. The `connection_pool` provides added context such as the connection used diff --git a/activerecord/lib/active_record/attribute_methods/primary_key.rb b/activerecord/lib/active_record/attribute_methods/primary_key.rb index 0dc792f452..63759ad462 100644 --- a/activerecord/lib/active_record/attribute_methods/primary_key.rb +++ b/activerecord/lib/active_record/attribute_methods/primary_key.rb @@ -133,8 +133,7 @@ def get_primary_key(base_name) # :nodoc: base_name.foreign_key else if ActiveRecord::Base != self && table_exists? - pk = connection.schema_cache.primary_keys(table_name) - suppress_composite_primary_key(pk) + connection.schema_cache.primary_keys(table_name) else "id" end @@ -178,16 +177,6 @@ def inherited(base) @quoted_primary_key = nil end end - - def suppress_composite_primary_key(pk) - return pk unless pk.is_a?(Array) - - warn <<~WARNING - WARNING: Active Record does not support composite primary key. - - #{table_name} has composite primary key. Composite primary key is ignored. - WARNING - end end end end diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb index 2cfead5b98..96d68feff2 100644 --- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb @@ -166,19 +166,6 @@ def test_proper_usage_of_primary_keys_and_join_table assert_equal 1, country.treaties.count end - def test_join_table_composite_primary_key_should_not_warn - country = Country.new(name: "India") - country.country_id = "c1" - country.save! - - treaty = Treaty.new(name: "peace") - treaty.treaty_id = "t1" - warning = capture(:stderr) do - country.treaties << treaty - end - assert_no_match(/WARNING: Active Record does not support composite primary key\./, warning) - end - def test_has_and_belongs_to_many david = Developer.find(1) diff --git a/activerecord/test/cases/primary_keys_test.rb b/activerecord/test/cases/primary_keys_test.rb index 7f2f3f03e7..36411593cd 100644 --- a/activerecord/test/cases/primary_keys_test.rb +++ b/activerecord/test/cases/primary_keys_test.rb @@ -463,16 +463,16 @@ def test_id_predicate_composite end end - def test_primary_key_issues_warning - model = Class.new(ActiveRecord::Base) do - def self.table_name - "uber_barcodes" + def test_derives_composite_primary_key + def test_primary_key_issues_warning + model = Class.new(ActiveRecord::Base) do + def self.table_name + "uber_barcodes" + end end + + assert_equal ["region", "code"], model.primary_key end - warning = capture(:stderr) do - assert_nil model.primary_key - end - assert_match(/WARNING: Active Record does not support composite primary key\./, warning) end def test_collectly_dump_composite_primary_key diff --git a/activerecord/test/models/cpk/book.rb b/activerecord/test/models/cpk/book.rb index cdfde3bfd3..7208c70c06 100644 --- a/activerecord/test/models/cpk/book.rb +++ b/activerecord/test/models/cpk/book.rb @@ -3,7 +3,6 @@ module Cpk class Book < ActiveRecord::Base self.table_name = :cpk_books - self.primary_key = [:author_id, :number] belongs_to :order, autosave: true, query_constraints: [:shop_id, :order_id] belongs_to :author, class_name: "Cpk::Author" diff --git a/activerecord/test/models/cpk/order.rb b/activerecord/test/models/cpk/order.rb index d1b7d6375a..6fc5a326a8 100644 --- a/activerecord/test/models/cpk/order.rb +++ b/activerecord/test/models/cpk/order.rb @@ -3,6 +3,8 @@ module Cpk class Order < ActiveRecord::Base self.table_name = :cpk_orders + # explicit definition is to allow schema definition to be simplified + # to be shared between different databases self.primary_key = [:shop_id, :id] has_many :order_agreements, primary_key: :id