You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Would it be possible to use Fragments just for pure re-usability? (without forced parent-child component encapsulation) #76
the main reason for fragments to exist is re-usability. It certainly emphasizes that it is specially useful when collocating with components, but it does NOT say that this is the only usage that we should be able to make out of it.
In the documentation (see collocated fragments), somehow states that there are two types of fragments, the ones that are "externally" (or collaterally) referred to by a component, and the ones that are defined right on that component (collated):
A colocated fragment is just like any other fragment, except it's defined in the same file as a particular component that uses the fragment's fields.
After you define a fragment in a child component, the parent component can refer to it in its own colocated fragments, like so:
exportconstFEED_ENTRY_FRAGMENT=gql`
fragment FeedEntryFragment on FeedEntry {
commentCount
repository {
full_name
html_url
owner {
avatar_url
}
}
...VoteButtonsFragment
...EntryInfoFragment
}
${VOTE_BUTTONS_FRAGMENT}${ENTRY_INFO_FRAGMENT}
In this example VOTE_BUTTONS_FRAGMENT and ENTRY_INFO_FRAGMENT are defined in (or imported from) child components.
Apollo's technique to define fragments and identify if they belong to a parent or children classes can arguable, yet they offer a way.
Following the example of graphlient gem, where fragments support was added by making it aligned with graphql-client, in the following query...
moduleFragmentsInvoice=client.parse<<~'GRAPHQL' fragment on Invoice { id feeInCents } GRAPHQLendinvoice_query=client.parsedoquerydoinvoice(id: 10)doid___Fragments__Invoiceendendend
... we would get the error if trying to access feeInCents directly from the query Response
changed the title [-]Would it be possible to use Fragments without parent-child component encapsulation?[/-][+]Would it be possible to use Fragments just for pure re-usability? (without forced parent-child component encapsulation)[/+]on Jul 9, 2025
Picking this up — short answer: yes, this is now supported, and it works exactly the way the original question hoped (Apollo-style).
How to do it today
Define a standard named GraphQL fragment inline, in the same parse string as the operation that spreads it, and its fields are directly accessible on the result — no ImplicitlyFetchedFieldError, no re-wrapping through a fragment constant:
Queries=Client.parse<<-'GRAPHQL' fragment UserDetails on User { fullName location } query UserQuery { user(name: "Josh") { ...UserDetails } }GRAPHQLresult=Client.query(Queries::UserQuery)result.data.user.full_name# works — inline fragment, no isolation enforcedresult.data.user.location# works
This mirrors Apollo Client's colocating fragments convention: a fragment used purely for reuse, defined next to its operation, fields accessible — without forcing a parent–child component hierarchy. The constant-bound style (fragment on Type { … } assigned to a Ruby constant) is still there for when you do want ImplicitlyFetchedFieldError to guard cross-module access. The two are complementary, and you pick per fragment.
What I've opened
docs: document inline (colocated) named fragments #80 — documents the inline / colocated style in the README and the ImplicitlyFetchedFieldError guide. This behaviour already existed in Client#parse (the local definition is kept and the fields flow through source_document) — it just wasn't documented anywhere.
fix: anchor inline fragment-definition detection in Client#parse #82 — hardens the parser. The spread/definition disambiguation used an unanchored match
(/fragment\s*#{const_name}/), which matched too eagerly: a ...UserFields spread could be mistaken for a fragment UserFieldsExtended on User definition and left unresolved (which actually crashed parsing in sliced_definitions).
It's now anchored to fragment <Name> on, with tests for the prefix-collision case and for a constant fragment coexisting with a prefix-sharing inline fragment (the realistic migration case).
Status
I'm leaving this issue open until #82 merges and ships — at that point the "fragments for pure reuse,
Apollo-style" request here is fully and robustly resolved, and I'll close it referencing the release.
@rmosolgo I have had a look at your roadmap to make sure this gem goes up. Could you please have a look at what has been done here, and give me your 5 cents on whether that's the path that we can take to make this gem scalable? (i.e. conventional re-using fragments via inline VS parent-child encapsulation via constants; backwards compatibility and convention-over-configuration principle + aligned with an industry reference: Apollo).
There are several MRs I have raised, each one with its own piece, so it gets easier to review and merge.
I know this may seem playing on the edge, at the current status and pace, but it is really going to be a booster. There are far more MRs I would like to contribute with to this particular gem. But first, there's need to remove some functional blockers.
@josh@jhawthorn@jmeridth ... could you please have a look at these 4 MRs and allow workflow checks? You can be selective and reject any MR if you see doesn't fit. Thank you!
Activity
[-]Would it be possible to use Fragments without parent-child component encapsulation?[/-][+]Would it be possible to use Fragments just for pure re-usability? (without forced parent-child component encapsulation)[/+]rellampec commentedon Aug 5, 2025
I guess this library isn't maintained any longer ??
rellampec commentedon Jun 15, 2026
Picking this up — short answer: yes, this is now supported, and it works exactly the way the original question hoped (Apollo-style).
How to do it today
Define a standard named GraphQL fragment inline, in the same
parsestring as the operation that spreads it, and its fields are directly accessible on the result — noImplicitlyFetchedFieldError, no re-wrapping through a fragment constant:This mirrors Apollo Client's colocating fragments convention: a fragment used purely for reuse, defined next to its operation, fields accessible — without forcing a parent–child component hierarchy. The constant-bound style (
fragment on Type { … }assigned to a Ruby constant) is still there for when you do wantImplicitlyFetchedFieldErrorto guard cross-module access. The two are complementary, and you pick per fragment.What I've opened
ImplicitlyFetchedFieldErrorguide. This behaviour already existed inClient#parse(the local definition is kept and the fields flow throughsource_document) — it just wasn't documented anywhere.Client#parsefragment-resolution behaviour, so the fix below can't change it silently.(
/fragment\s*#{const_name}/), which matched too eagerly: a...UserFieldsspread could be mistaken for afragment UserFieldsExtended on Userdefinition and left unresolved (which actually crashed parsing insliced_definitions).It's now anchored to
fragment <Name> on, with tests for the prefix-collision case and for a constant fragment coexisting with a prefix-sharing inline fragment (the realistic migration case).Status
I'm leaving this issue open until #82 merges and ships — at that point the "fragments for pure reuse,
Apollo-style" request here is fully and robustly resolved, and I'll close it referencing the release.
rellampec commentedon Jun 23, 2026
@rmosolgo I have had a look at your roadmap to make sure this gem goes up. Could you please have a look at what has been done here, and give me your 5 cents on whether that's the path that we can take to make this gem scalable? (i.e. conventional re-using fragments via inline VS parent-child encapsulation via constants; backwards compatibility and convention-over-configuration principle + aligned with an industry reference: Apollo).
There are several MRs I have raised, each one with its own piece, so it gets easier to review and merge.
I know this may seem playing on the edge, at the current status and pace, but it is really going to be a booster. There are far more MRs I would like to contribute with to this particular gem. But first, there's need to remove some functional blockers.
rellampec commentedon Jun 29, 2026
@josh @jhawthorn @jmeridth ... could you please have a look at these 4 MRs and allow workflow checks? You can be selective and reject any MR if you see doesn't fit. Thank you!