My data model has two resources: Folder
and Messages
. Each message belongs to a folder. Sometimes I'll want to get a list of folders (including some fields for each folder). Sometimes I'll want to get the details of a particular folder (including some fields and messages for that folder).
In a Rails/RESTful system, this would correspond to the index
and show
actions on the Folder
resource; the latter would receive the id
parameter specifying the desired folder. What would this schema look like in "idiomatic" GraphQL?
One approach might be have one field for each action:
type Query {
folders: [Folder]
folder(id: String!): Folder
}
There's some duplication here, which seems messy and makes it harder for an client to introspect and understand the schema.
Perhaps the duplication can be removed with a nullable argument:
type Query {
folder(id: String): [Folder]
}
If an id
is passed, just the details of that Folder
will be returned (as a one-item array). If id
is nil
, then it'll get the details for all folders. This overloading seems to add some hidden complexity.
Which approach is "better practice"? Is there a better way to model this situation?
TLDR: Fields are cheap, use them.
I'd suggest the first approach. In the same way a REST API can get hopelessly muddled with flags to trigger different behaviors, so can a field with various arguments. By making two different fields, you can also let the type system give stronger client guarantees:
type Query {
folders: [Folder!]!
folder(id: String!): Folder
}
In this case, you'll always get some sort of list back for folders
, and it won't contain any null
s. Emptiness is just the empty list. The API documents itself, which may not be the case if you try to mash an increasing number of optional arguments into one field.
Also, if you need to paginate folders
, you'll need pagination-specific arguments for that endpoint, and perhaps the intermediate structure of the connection pattern.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With