Automatically inverse_of with custom foreign keys #43946
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Background
Along the same lines as 518b9a3, this commit allows us to automatically detect the
inverse_of
for associations with custom foreign_keys by searching through the reflections on the target class.For GitHub, this adds
inverse_of
to 161 associations that didn't have it before (and a total of nearly 300 associations when combined withautomatic_scope_inversing
). Of those we had 4 associations that relied on the old behavior and so I addedinverse_of: false
to those for now.Approach
With this commit we first try to find the association by name as before, but if that doesn't work we scan through the reflections on the target class and look for one that has matching options. To ensure we've really got a match we have to check just about everything—foreign_key, primary_key, class, macro, etc.
This commit reorders
valid_inverse_reflection?
a bit to ensure we filter out polymorphic reflections earlier (they can blow up when callingreflection.foreign_key
), but other callers of the method shouldn't see any difference in behavior.Since this is a breaking change (existing code may rely on a missing
inverse_of
causing fresh copies of a record to be loaded), the behavior is behind theautomatic_foreign_key_inversing
flag. It is set to true for new applications via framework defaults.Alternatives Considered
I started off by of chopping off the "_id" part of the foreign key option to try and guess the inverse name, but that worked for fewer cases than this does.
Performance considerations:
Scanning through reflections to find valid ones could be inefficient on
classes with a large number of associations.
GitHub does have a couple classes with > 100 associations, however the vast majority have only a few (4-5 on average). Eagerly loading all of our inverses takes about 160ms of reflection scanning with this change, which I think is an acceptable tradeoff for us given the number of queries these inverses are likely to save us.