Skip to content

Commit 82fca55

Browse files
authored
Merge pull request rails#47810 from Shopify/pm/fixture-id
Generate unique members of a composite key in fixtures
2 parents e8b47dd + f7062f2 commit 82fca55

File tree

3 files changed

+37
-5
lines changed

3 files changed

+37
-5
lines changed

activerecord/lib/active_record/fixture_set/table_row.rb

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ def fill_row_model_attributes
8787
return unless model_class
8888
fill_timestamps
8989
interpolate_label
90-
generate_primary_key
90+
model_class.composite_primary_key? ? generate_composite_primary_key : generate_primary_key
9191
resolve_enums
9292
resolve_sti_reflections
9393
end
@@ -117,14 +117,28 @@ def interpolate_label
117117
end
118118

119119
def generate_primary_key
120-
# generate a primary key if necessary
121-
Array(model_metadata.primary_key_name).each do |pk|
122-
next if !model_metadata.has_column?(pk) || @row.include?(pk)
120+
pk = model_metadata.primary_key_name
123121

122+
unless column_defined?(pk)
124123
@row[pk] = ActiveRecord::FixtureSet.identify(@label, model_metadata.column_type(pk))
125124
end
126125
end
127126

127+
def generate_composite_primary_key
128+
id = ActiveRecord::FixtureSet.identify(@label)
129+
model_metadata.primary_key_name.each_with_index do |column, index|
130+
next if column_defined?(column)
131+
raise "Automatic key generation assumes columns of type Integer." unless model_metadata.column_type(column) == :integer
132+
133+
# Shift label identifier index-#-of-times to differentiate sub-components in deterministic manner.
134+
@row[column] = (id << index) % ActiveRecord::FixtureSet::MAX_ID
135+
end
136+
end
137+
138+
def column_defined?(col)
139+
!model_metadata.has_column?(col) || @row.include?(col)
140+
end
141+
128142
def resolve_enums
129143
reflection_class.defined_enums.each do |name, values|
130144
if @row.include?(name)

activerecord/test/cases/fixtures_test.rb

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1643,13 +1643,26 @@ def readonly_config
16431643
end
16441644

16451645
class CompositePkFixturesTest < ActiveRecord::TestCase
1646-
fixtures :cpk_orders, :cpk_books
1646+
fixtures :cpk_orders, :cpk_books, :authors
1647+
1648+
def test_generates_composite_primary_key_for_partially_filled_fixtures
1649+
david = authors(:david)
1650+
david_cpk_book = cpk_books(:cpk_known_author_david_book)
1651+
1652+
assert_not_empty(david_cpk_book.id.compact)
1653+
assert_equal david.id, david_cpk_book.author_id
1654+
assert_not_nil david_cpk_book.number
1655+
end
16471656

16481657
def test_generates_composite_primary_key_ids
16491658
assert_not_empty(cpk_orders(:cpk_groceries_order_1).id.compact)
16501659

16511660
assert_not_nil(cpk_books(:cpk_great_author_first_book).author_id)
16521661
assert_not_nil(cpk_books(:cpk_great_author_first_book).number)
16531662
end
1663+
1664+
def test_generates_composite_primary_key_with_unique_components
1665+
assert_equal 2, cpk_orders(:cpk_groceries_order_1).id.uniq.size
1666+
end
16541667
end
16551668
end

activerecord/test/fixtures/cpk_books.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,8 @@ cpk_great_author_second_book:
1212
cpk_famous_author_first_book:
1313
title: "Ruby on Rails"
1414
revision: 1
15+
16+
cpk_known_author_david_book:
17+
author_id: 1
18+
title: "David's CPK Book"
19+
revision: 1

0 commit comments

Comments
 (0)