This project is archived and is in readonly mode.
[PATCH] Refactoring JoinDependency and friends
-
Bodaniel Jeanes
Jon, perhaps prefix the title of this ticket with [PATCH] so they know there's a patch to apply/test instead of a problem to solve.
FWIW, +1 and this change introduces no extra detectable bugs and will go along way with regards to Jon and I finishing integrated nested has_many :through support in #1152
-
Jon Leighton
- Title changed from Refactoring JoinDependency and friends to [PATCH] Refactoring JoinDependency and friends
-
Jon Leighton
I thought that the 'patch' tag was the official way to do it, but if [PATCH] in the title helps then why not :)
-
Ryan Bigg
- Importance changed from to Low
+1 from me too. This patch applies cleanly and the tests run.
-
Ryan Bigg
- Importance changed from Low to Medium
-
Alex MacCaw
+1
-
Jon Leighton
- Tag changed from activerecord, associations, patch to activerecord, associations, patch, verified
-
Jon Leighton
- Assigned user set to Santiago Pastorino
Assigning to Santiago as that's what it says to do here: https://rails.lighthouseapp.com/projects/8994/ticket-assignment
-
Santiago Pastorino
- Assigned user changed from Santiago Pastorino to Aaron Patterson
-
Aaron Patterson
- State changed from new to needs-more-info
Hi @Jon,
It's very difficult for me to review this patch. Could you break it up in to multiple patches please? It looks like you're renaming variables and changing formatting. It's difficult for me to tell whether you're just renaming and reformatting, or actually changing stuff.
Would you mind breaking this up to one patch that does formatting and renaming changes, and one patch that makes any refactors (like new methods, etc)?
Thanks.
-
Jon Leighton
Hi Aaron,
Thanks for taking time to look at this, and sorry that my patch confused you.
I'm happy to split it up if that helps, but I thought perhaps it might be more useful if I provided a better explanation of what the patch actually changes. (Admittedly I should have done this originally.)
- Currently
JoinAssociationhas the methods#relation,#association_joinand#join_class. These are used together inActiveRecord::QueryMethods.build_joinsto build up the joins which are necessary to join an association onto a query. - The current situation is that joining an association will
either result in one or two actual SQL
JOINstatements being generated (depending on whether the association in question involves a join table or not). The way thatJoinAssociationdeals with this is to have#relationeither output a singleArel::Tablefor a single join, or to output an array containing twoArel::Tables, for two joins. In the latter case,#association_joinalso outputs an array which has the different conditions for different joins at different positions in the array. - The work I am doing on having arbitrarily nested associations
(x goes through y which in turn goes through z) means that the
current
JoinAssociationis inflexible for this, because it is geared towards only having either one or two joins. Additionally the code already uses special cases in different situations to achieve its ends (for example, testing whether the return value ofassociation.relationis an array or not, inbuild_joins). - I wanted to refactor how
JoinAssociationandbuild_joinsworked to make them more generic.
This is the basic rationale. In terms of what I actually did:
- As I said, currently
JoinAssociationhas various methods which output various things.build_joinsuses their output to produce the actual join, e.g.relation.join(some_table).on(*some_conditions). - Instead of this, I let
JoinAssociationhave a#join_to(relation)method, with the idea thatJoinAssociationwould now be responsible for adding as many joins to the relation as are necessary.#join_towould then return a relation with the joins added. This prevents the situation of having to pass around arrays where the different positions in the arrays take on a special meaning, etc. - As you can see in the patch, this makes the code in
build_joinsa lot nicer - instead of all that stuff with building up theto_joinarray, we just iterate each of theJoinAssociations and dorelation = association.join_to(relation)
I also made some slightly more cosmetic changes, which seemed to 'make sense' as part of it:
- Currently
JoinAssociationis a subclass ofJoinBase. Instead I created an abstractJoinPartclass whichJoinAssociationandJoinBaseboth individually inherit from. This seems cleaner to me, as I don't think aJoinAssociationis a type ofJoinBase, though they are related. For exampleJoinBasehas thetable_joinsattribute which means nothing toJoinAssociation. - Due to the addition of this
JoinPartsuperclass, I thought it was more consistent to name the collection inJoinDependencytojoin_partsinstead of justjoins - I also renamed
JoinAssociation#join_classtojoin_type. This is purely me being opinionated about what it should be called. I'm not attached to that name and it doesn't fundamentally matter either way. - I didn't make any sweeping formatting changes or anything like that.
- I didn't change any of the logic which actually builds the joins and their conditions.
I hope this explanation helps. I'm willing to break up the patch if you'd still like me too, but obviously happy to avoid that work if possible :) Let me know how you think it's best to proceed.
Cheers,
Jon - Currently
-
Jon Leighton
Also - if you'd like to have a chat on Skype or anything like that then let me know.
-
Aaron Patterson
Damn! Thanks for the detailed explanation, I really appreciate it. The problem though, is that the first ~200 lines of the patch are mostly formatting and changing variable names. I think there might be one or two lines out of the first 200 that are substantial.
I'm in favor of fixing formatting and changing variable names, but it doesn't help me understand the core of the patch. I like your description of the changes and I am in favor of adding this functionality, but please split this up.
I would really like one patch that does variable renaming and formatting changes, and one that adds / changes functionality. Not just to help me understand what you're changing, but to help people in the future. If there are bugs in your patch, I don't want people to have to wade through a 40k diff to find them.
-
Jon Leighton
Ok, no worries. I will split it up, hopefully within the next 24 hours.
-
Jon Leighton
Okay, here is the split up patch. There are actually four commits now:
- Add 3 new tests for existing functionality, and fix up other
tests affected by changing the fixtures
- Do the "core changes" talked about here
- Renaming/formating changes
- I took the liberty of deleting two methods from JoinAssociation which are not used anywhere.
I have verified that the entire test suite still succeeds after these changes.
Hope this helps.
Cheers
- Add 3 new tests for existing functionality, and fix up other
tests affected by changing the fixtures
-
Aaron Patterson
- State changed from needs-more-info to committed
@Jon awesome. Much easier to review. I've applied all your patches to master and pushed. Thank you very much!
