mirror of https://github.com/rails/rails
Raise error on invalid fixture primary key
When you're using a custom primary key on a belongs_to and you're trying to load that value through the association shorthand in a fixture, you end up getting the primary key of the table and not the primary key specified in the join. This makes sense to keep as the behavior because it's super fast (just hashing the name of the fixture), but it's still surprising so we should want the developer that it's not possible to do what they want.
This commit is contained in:
parent
c9cdf7410e
commit
006eb25ccd
|
@ -39,6 +39,29 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
class PrimaryKeyError < StandardError # :nodoc:
|
||||
def initialize(label, association, value)
|
||||
super(<<~MSG)
|
||||
Unable to set #{association.name} to #{value} because the association has a
|
||||
custom primary key (#{association.join_primary_key}) that does not match the
|
||||
associated table's primary key (#{association.klass.primary_key}).
|
||||
|
||||
To fix this, change your fixture from
|
||||
|
||||
#{label}:
|
||||
#{association.name}: #{value}
|
||||
|
||||
to
|
||||
|
||||
#{label}:
|
||||
#{association.foreign_key}: **value**
|
||||
|
||||
where **value** is the #{association.join_primary_key} value for the
|
||||
associated #{association.klass.name} record.
|
||||
MSG
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(fixture, table_rows:, label:, now:)
|
||||
@table_rows = table_rows
|
||||
@label = label
|
||||
|
@ -119,9 +142,13 @@ module ActiveRecord
|
|||
fk_name = association.join_foreign_key
|
||||
|
||||
if association.name.to_s != fk_name && value = @row.delete(association.name.to_s)
|
||||
if association.polymorphic? && value.sub!(/\s*\(([^)]*)\)\s*$/, "")
|
||||
# support polymorphic belongs_to as "label (Type)"
|
||||
@row[association.join_foreign_type] = $1
|
||||
if association.polymorphic?
|
||||
if value.sub!(/\s*\(([^)]*)\)\s*$/, "")
|
||||
# support polymorphic belongs_to as "label (Type)"
|
||||
@row[association.join_foreign_type] = $1
|
||||
end
|
||||
elsif association.join_primary_key != association.klass.primary_key
|
||||
raise PrimaryKeyError.new(@label, association, value)
|
||||
end
|
||||
|
||||
fk_type = reflection_class.type_for_attribute(fk_name).type
|
||||
|
|
|
@ -6,6 +6,7 @@ require "models/admin"
|
|||
require "models/admin/account"
|
||||
require "models/admin/randomly_named_c1"
|
||||
require "models/admin/user"
|
||||
require "models/author"
|
||||
require "models/binary"
|
||||
require "models/book"
|
||||
require "models/bulb"
|
||||
|
@ -18,6 +19,7 @@ require "models/course"
|
|||
require "models/developer"
|
||||
require "models/dog"
|
||||
require "models/doubloon"
|
||||
require "models/essay"
|
||||
require "models/joke"
|
||||
require "models/matey"
|
||||
require "models/other_dog"
|
||||
|
@ -1492,6 +1494,16 @@ class FileFixtureConflictTest < ActiveRecord::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
class PrimaryKeyErrorTest < ActiveRecord::TestCase
|
||||
test "generates the correct value" do
|
||||
e = assert_raise(ActiveRecord::FixtureSet::TableRow::PrimaryKeyError) do
|
||||
ActiveRecord::FixtureSet.create_fixtures(FIXTURES_ROOT + "/primary_key_error", "primary_key_error")
|
||||
end
|
||||
|
||||
assert_includes e.message, "Unable to set"
|
||||
end
|
||||
end
|
||||
|
||||
if current_adapter?(:SQLite3Adapter) && !in_memory_db?
|
||||
class MultipleFixtureConnectionsTest < ActiveRecord::TestCase
|
||||
include ActiveRecord::TestFixtures
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
_fixture:
|
||||
model_class: Author
|
||||
|
||||
david:
|
||||
name: David
|
||||
owned_essay: a_modest_proposal
|
Loading…
Reference in New Issue