Repository navigation
Would it be possible to use Fragments just for pure re-usability? (without forced parent-child component encapsulation) #76
Description
Activity
- 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 I guess this library isn't maintained any longer ??
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:Queries = Client.parse <<-'GRAPHQL' fragment UserDetails on User { fullName location } query UserQuery { user(name: "Josh") { ...UserDetails } } GRAPHQL result = Client.query(Queries::UserQuery) result.data.user.full_name # works — inline fragment, no isolation enforced result.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 wantImplicitlyFetchedFieldErrorto 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
ImplicitlyFetchedFieldErrorguide. This behaviour already existed inClient#parse(the local definition is kept and the fields flow through
source_document) — it just wasn't documented anywhere. - test: characterize Client#parse handling of inline named fragments #81 — characterization tests that pin the current
Client#parsefragment-resolution behaviour, so the fix below can't change it silently. - 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...UserFieldsspread could be mistaken for afragment UserFieldsExtended on Userdefinition and left unresolved (which actually crashed parsing insliced_definitions).
It's now anchored tofragment <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.- docs: document inline (colocated) named fragments #80 — documents the inline / colocated style in the README and the
@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!
In regards to the
ImplicitlyFetchedFieldError, that is raised inGraphQL::Client::Schema::ObjectType, onmethod_missing...Would it be possible to have the option to use fragments just for re-usability?
For example, in the Apollo documentation on fragments, it states that
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):
VOTE_BUTTONS_FRAGMENTandENTRY_INFO_FRAGMENTare 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
graphlientgem, where fragments support was added by making it aligned withgraphql-client, in the following query...... we would get the error if trying to access
feeInCentsdirectly from the queryResponseHow would we in
graphql-clientdefine a fragment that belongs to the main query (or parent component)?provided that we can do something like this:
without getting the error
GraphQL::Client::ImplicitlyFetchedFieldError.