Fix potential scope leakage in ThroughAssociationPatch#167
Fix potential scope leakage in ThroughAssociationPatch#167oehlschl wants to merge 2 commits intosalsify:masterfrom
Conversation
jturkel
left a comment
There was a problem hiding this comment.
Thanks for the PR @oehlschl. Apologies for the delay getting around to a review.
This sounds like a pretty nasty bug! I spent some time trying to narrow down the Rails bug to ensure we can workaround it properly in goldiloader and file a Rails bug. I was able to trigger it using this gist with a filtered and unfiltered through association. Is this a more general issue of Rails eager loading ignoring any through association scope customizations if there's a similar through association without any scope customizations that's loaded first?
|
Hi @jturkel; apologies for the delayed response as well.
I would believe that. I didn't go so far as to file the Rails bug yet, as it took a while just to get this far, so if you feel like you have a better handle on it, please feel free, or let me know what you need. |
|
I filed rails/rails#56110. Let's see what the Rails maintainers say and then we can workaround the issue as needed. |
Fixes #166
Problem
This PR fixes bug where scopes from one
has_many :throughassociation leak into queries for other through associations when the owner model has adefault_scopewith an ORDER BY clause. This bug was introduced in version 4.2.1 with theThroughAssociationPatchand affects all versions through the current (5.4.0).The
ThroughAssociationPatchmodule enables auto-including through associations after the through association has been loaded. However, when the owner model has adefault_scope, Rails' association preloader incorrectly reuses scoped queries across different through associations, causing scope leakage. This is arguably a Rails bug in the association preloader, but we need to work around it in Goldiloader by detecting when this pattern exists and disabling the optimization in those cases.Fix
This PR adds a
has_scope_leakage_risk?check to theThroughAssociationPatchthat:default_scopewith ORDER BYfalsefromauto_include?when that case exists, preventing scope leakageThe fix uses instance-level caching for performance, ensuring the detection logic only runs once per association.
And again, this may be more of a "workaround" then a fix, as the function of this PR is to disable the optimzation added in 4.2.1 when this buggy case exists.
Changes
has_scope_leakage_risk?detection method toThroughAssociationPatchresolve_check_class,class_has_order_default_scope?,has_other_scoped_through_associations?@order_scope_cache,@scoped_through_cache)Testing
Tests cases show that Goldiloader:
Conclusion
The fix does add some complexity but should be performant and backwards compatible.The fix ensures these apps with these cases get correct query results while maintaining Goldiloader's performance benefits where safe to do so.