-
Notifications
You must be signed in to change notification settings - Fork 22k
Add composite primary key validity check on belongs_to, has_one, and has_many associations. #48357
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to be very handy to avoid ambiguous error messages when defining associations from/to a model with a composite primary key. Thanks!
I have a suspicion that the validation check can eventually be moved to the parent class so we check the condition for any type of the association. However I'm okay if we start from belongs_to
and consider expanding it once we have another failing test-case
def check_validity! | ||
super | ||
|
||
if !polymorphic? && klass.composite_primary_key? && Array(association_primary_key).length != Array(foreign_key).length |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The validation is true for any type of the model so klass.composite_primary_key?
check is not necessary from the design point of view. However we can kind of use it to prevent unnecessary arrays allocation for non-cpk models. So it's up to you too keep it
if !polymorphic? && klass.composite_primary_key? && Array(association_primary_key).length != Array(foreign_key).length | |
if !polymorphic? && Array(association_primary_key).length != Array(foreign_key).length |
If we are going to keep it I think we designed association_primary_key
and foreign_key
to be an array if the klass
is a cpk model, so potentially we should be able to do:
if !polymorphic? && klass.composite_primary_key? && Array(association_primary_key).length != Array(foreign_key).length | |
if !polymorphic? && klass.composite_primary_key? && association_primary_key.length != foreign_key.length |
though I could be missing something
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe removing the composite PK check makes the tests for query_constraints
that use models under Sharded::
fail. In this case, query_constraints
don't necessarily map to FKs AFAICT.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to be very handy to avoid ambiguous error messages when defining associations from/to a model with a composite primary key. Thanks!
I have a suspicion that the validation check can eventually be moved to the parent class so we check the condition for any type of the association. However I'm okay if we start from belongs_to
and consider expanding it once we have another failing test-case
|
||
def initialize(reflection = nil) | ||
if reflection | ||
@reflection = reflection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't appear to be necessary, where is this used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It isn't, but a lot of inverse and association validity errors seem to have that accessor and ivar for some reason. I'll remove it 👍
6aa85e1
to
22fcbac
Compare
Raise ActiveRecord::CompositePrimaryKeyMismatchError when a belongs_to, has_one, or has_many foreign key and primary key don't have the same length.
Motivation / Background
This Pull Request has been created because belongs_to associations with composite primary keys are broken.
Detail
Raises
ActiveRecord::CompositePrimaryKeyMismatchError
whenbelongs_to
foreign key and primary key don't have the same length.Additional information
This fixes an issue where autosave fails to update foreign key attributes here:
rails/activerecord/lib/active_record/autosave_association.rb
Lines 511 to 515 in ced5e77
I'm not sure if my fix is the best way to fix this problem, there might be an easier way around this than introducing an error and additional validation check. From my perspective, if a model has a composite primary key, its associations need query constraints to spell out the foreign key columns Active Record should use. Let me know what you think!
Checklist
Before submitting the PR make sure the following are checked:
[Fix #issue-number]