Skip to content

Commit 791f109

Browse files
authored
Merge pull request rails#47633 from Shopify/allow-deriving-composite-primary-key-from-schema
Allow composite primary key to be derived from schema
2 parents e7be1e7 + 257f012 commit 791f109

File tree

6 files changed

+29
-34
lines changed

6 files changed

+29
-34
lines changed

activerecord/CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
* Allow composite primary key to be derived from schema
2+
3+
Booting an application with a schema that contains composite primary keys
4+
will not issue warning and won't `nil`ify the `ActiveRecord::Base#primary_key` value anymore.
5+
6+
Given a `travel_routes` table definition and a `TravelRoute` model like:
7+
```ruby
8+
create_table :travel_routes, primary_key: [:origin, :destination], force: true do |t|
9+
t.string :origin
10+
t.string :destination
11+
end
12+
13+
class TravelRoute < ActiveRecord::Base; end
14+
```
15+
The `TravelRoute.primary_key` value will be automatically derived to `["origin", "destination"]`
16+
17+
*Nikita Vasilevsky*
18+
119
* Include the `connection_pool` with exceptions raised from an adapter.
220

321
The `connection_pool` provides added context such as the connection used

activerecord/lib/active_record/attribute_methods/primary_key.rb

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,7 @@ def get_primary_key(base_name) # :nodoc:
133133
base_name.foreign_key
134134
else
135135
if ActiveRecord::Base != self && table_exists?
136-
pk = connection.schema_cache.primary_keys(table_name)
137-
suppress_composite_primary_key(pk)
136+
connection.schema_cache.primary_keys(table_name)
138137
else
139138
"id"
140139
end
@@ -178,16 +177,6 @@ def inherited(base)
178177
@quoted_primary_key = nil
179178
end
180179
end
181-
182-
def suppress_composite_primary_key(pk)
183-
return pk unless pk.is_a?(Array)
184-
185-
warn <<~WARNING
186-
WARNING: Active Record does not support composite primary key.
187-
188-
#{table_name} has composite primary key. Composite primary key is ignored.
189-
WARNING
190-
end
191180
end
192181
end
193182
end

activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -166,19 +166,6 @@ def test_proper_usage_of_primary_keys_and_join_table
166166
assert_equal 1, country.treaties.count
167167
end
168168

169-
def test_join_table_composite_primary_key_should_not_warn
170-
country = Country.new(name: "India")
171-
country.country_id = "c1"
172-
country.save!
173-
174-
treaty = Treaty.new(name: "peace")
175-
treaty.treaty_id = "t1"
176-
warning = capture(:stderr) do
177-
country.treaties << treaty
178-
end
179-
assert_no_match(/WARNING: Active Record does not support composite primary key\./, warning)
180-
end
181-
182169
def test_has_and_belongs_to_many
183170
david = Developer.find(1)
184171

activerecord/test/cases/primary_keys_test.rb

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -463,16 +463,16 @@ def test_id_predicate_composite
463463
end
464464
end
465465

466-
def test_primary_key_issues_warning
467-
model = Class.new(ActiveRecord::Base) do
468-
def self.table_name
469-
"uber_barcodes"
466+
def test_derives_composite_primary_key
467+
def test_primary_key_issues_warning
468+
model = Class.new(ActiveRecord::Base) do
469+
def self.table_name
470+
"uber_barcodes"
471+
end
470472
end
473+
474+
assert_equal ["region", "code"], model.primary_key
471475
end
472-
warning = capture(:stderr) do
473-
assert_nil model.primary_key
474-
end
475-
assert_match(/WARNING: Active Record does not support composite primary key\./, warning)
476476
end
477477

478478
def test_collectly_dump_composite_primary_key

activerecord/test/models/cpk/book.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
module Cpk
44
class Book < ActiveRecord::Base
55
self.table_name = :cpk_books
6-
self.primary_key = [:author_id, :number]
76

87
belongs_to :order, autosave: true, query_constraints: [:shop_id, :order_id]
98
belongs_to :author, class_name: "Cpk::Author"

activerecord/test/models/cpk/order.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
module Cpk
44
class Order < ActiveRecord::Base
55
self.table_name = :cpk_orders
6+
# explicit definition is to allow schema definition to be simplified
7+
# to be shared between different databases
68
self.primary_key = [:shop_id, :id]
79

810
has_many :order_agreements, primary_key: :id

0 commit comments

Comments
 (0)