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
merge parent joins for through associations #24682
merge parent joins for through associations #24682
Conversation
Thanks for the pull request, and welcome! The Rails team is excited to review your changes, and you should hear from @chancancode (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
@@ -134,13 +134,13 @@ def add_constraints(scope, owner, association_klass, refl, chain_head, chain_tai | |||
scope = next_chain_scope(scope, table, reflection, association_klass, foreign_table, next_reflection) | |||
end | |||
|
|||
# Exclude the scope of the association itself, because that | |||
# was already merged in the #scope method. |
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.
outdated comment
b420e1d
to
c7c1453
Compare
@@ -158,6 +158,20 @@ def add_constraints(scope, owner, association_klass, refl, chain_head, chain_tai | |||
scope | |||
end | |||
|
|||
def merge_joins(scope, other) | |||
joins_dependency, rest = other.joins_values.partition do |join| |
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 same code we have here https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation/merger.rb#L113
I think it will be good to extract it somewhere
Will be good to add tests for pure sql joins and maybe also extract the logic to some sort of a merger class, but I would like to here some feedback first. Am I moving in right direction? |
Can you please give more context in your commit message about what the issue is, why it occurs, and why this fixes it? "Fix joins in association scope" isn't much information for future readers. |
c7c1453
to
291bcf1
Compare
@sgrif, sorry for that, I've updated commit and pull request descriptions |
end | ||
|
||
join_dependency = ActiveRecord::Associations::JoinDependency.new(other.klass, joins_dependency, rest) | ||
scope.joins! join_dependency.join_constraints([], Arel::Nodes::InnerJoin).map(&:joins) |
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 also need to merge outer joins
291bcf1
to
9e9e484
Compare
Merges parent associations joins for through associations into a scope. Previously joins in association scope were taken into account only for root associations with that scope.
9e9e484
to
2767ea5
Compare
Rails converts inner joins to outer joins when merging #24281 That maybe strange and counterintuitive that If #24281 is bug that needs to be fixed, than I'll be able to use |
@sgrif Any chance this can be merged soon? |
Just ran into this. It breaks quite a few |
|
||
if scope_chain_item == refl.scope | ||
scope.merge! item.except(:where, :includes) | ||
elsif item.joins_values.any? | ||
merge_joins(scope, item) |
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.
How is this different than the merge that will occur in the call to scope.merge!
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.
scope.merge!
merges joins with Relation::Merger
, which converts inner joins to outer when merge_joins
doesn't do that
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.
That doesn't appear to be the case. The code is almost exactly identical to what you have here. https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation/merger.rb#L107-L129
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.
Yes, it looks pretty much the same, but there are differences at the end. Instead of passing ActiveRecord::Associations::JoinDependency
instance to relation.joins!
, I pass an array of Arel::Nodes::InnerJoin
objects, which are built as inner joins instead of outer for JoinDependency
here
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation/query_methods.rb#L1015
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation/query_methods.rb#L1030
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation/query_methods.rb#L1042
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations/join_dependency.rb#L122
Is anyone working on this pr? |
@at-hatran, at the time there is nothing to work on in this pr. I am waiting for any comments. |
@sevaorlov I've just discovered this issue and my project use a lot of associations like this. Do you have any workaround for this? |
@at-hatran, just don't user merges in conditions. For example, you could create a separate Query class for that particular query. |
Summary
Fixes #22538
Merges parent association joins for through associations into a scope. These joins are not taken into account at all right now.
For example
direct_appointments
joinjoins(:role)
will not be merged fordirect_users
association and a call fordirect_users
will fail becausedirect
column will not be found inusers
table.My request adds these joins merging in association scope.
Other Information
I open request to master, but that issue is also present in Rails 4+, do I need to open requests to branches for 4+ versions?
Update
Also fixes #12933