Introduce decoupled query_constraints for associations#51
Open
nvasilevski wants to merge 2 commits into
Open
Conversation
Comment on lines
+532
to
+533
| # If the foreign key is an array, set query constraints options | ||
| if options[:foreign_key].is_a?(Array) && !options[:query_constraints] |
There was a problem hiding this comment.
If the idea is that we're separating the two concepts, do we still need to copy the value over?
Reintroduces query_constraints on associations, decoupled from foreign_key. When both are specified, foreign_key handles writes and query_constraints is used for querying association targets (loading and preloading).
27fce20 to
af51443
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Introduce decoupled
query_constraintsfor associationsReintroduces
query_constraintson associations, decoupled fromforeign_key.Mental model
query_constraintsis a list of additional columns to match when querying anassociation's targets (loading and preloading). They are layered on top of the
foreign key — the foreign key always participates, because an association can't be
queried without it.
foreign_keyis given → behaves exactly as today.foreign_keyandquery_constraintsare given →foreign_keyhandleswrites, and querying matches on
foreign_key+ the extra columns.query_constraintsis allowed, not rejected — itis de-duplicated.
Two sides of a constraint
A column can have a different name on each side.
query_constraintsaccepts symbols(same name on both sides) and hashes (
self_column => target_column):Resulting join keys:
BlogPost) columns:["blog_id", "id", "featured_comment_id"]Comment) columns:["blog_id", "blog_post_id", "id"]A Hash mapping requires an explicit
foreign_key(an FK can't be derived from arenamed pair) — otherwise an
ArgumentErroris raised.Implementation
query_constraints_foreign_key,normalized_query_constraints_mapping, andjoin_query_constraints_{primary,foreign}_key/join_query_constraints_id_for.Join (
join_scope,AssociationScope) and preload paths resolve keys throughthese, falling back to the existing
join_*behavior when noquery_constraintsare present.
active_record_primary_key(and autosave's write key) ignorequery_constraintswhen an explicit
foreign_keyis present, so writes and.joins()keep using thescalar PK/FK.
ThroughReflection/PolymorphicReflection/RuntimeReflectiondelegate the newmethods in lockstep with their
join_*counterparts.Backward compatibility
Old-style
query_constraints(a plain list of FK columns, no explicitforeign_key)keeps its previous meaning: the columns become the foreign key and
normalized_query_constraints_mappingreturnsnil.