-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mutation Patterns: Single vs Double Argument #23
Comments
After thinking about it maybe |
Interesting idea, but IMO only for very very flexible and SQL like experience. Two arguments pattern IMO doesn't give much of difference. I'm not lazy to nest things :) So I would rather say it's matter of taste. For instance, if you use a I would suggest in this case having a structure like movie {
bulkCreate(input: { data: [Movie!]! })
# behaves like SQL UPDATE
bulkUpdate(selector, data: MovieUpdatePayload!)
# behaves like SQL DELETE
bulkDelete(selector)
# behaves more like RESTish `POST`
create(input: { data: MovieCreatePayload!})
# behaves more like RESTish `PUT`
update(id: String!, input: { data: MovieUpdatePayload! }) # or just update(input: { id: String!, data:MovieCreatePayload!})
# etc...
} About the third argument e.g. Anyway, I really like single input for its ability to extend almost endlessly with no breaking or minimal breaking changes (which can lead to bad design, because too much freedom is bad, but still) I would say that for something super flexible, an approach that you suggest is ok. But for more of a handcrafted and limited to some constrains, single |
Thanks for the feedback! Maybe I'll stick to single argument then.
Would you have an example of this? Or maybe a link to some resources? This could actually be a good section for the project, since I expect this is a pretty common need. |
@nodkz hey man. Do you have any examples of custom directives with Apollo Server or similar, because I never wrote any myself. |
As an example in rule mutation-input-arg I provide the following code: # Good:
mutation ($input: UpdatePostInput!) {
updatePost(input: $input) { ... }
}
# Not so good – it's harder to write a query (duplication of variables)
mutation ($id: ID!, $newText: String, ...) {
updatePost(id: $id, newText: $newText, ...) { ... }
} In most cases when frontenders write mutations, they are using GraphQL-variables. And searching one type name for BUT if we say about just two or three top-level args like suggested @SachaG I don't see any big problems too. We are providing an opportunity to simplify eg I think that we should create a new
@SachaG you may prepare mutation ($id: ID!, $name: String, $lastname: String, dob: Date, gender: GenderEnum, city: String, ...) {
updatePost(id: $id, name: $name, lastname: $lastname, dob: $dob, gender: $gender, city: $city, ...) { ... }
} PS. Sorry guys in the delay of my answer, cause I just returned from HolyJS Conf and had no time to answer in time. I'm very sorry. But in a couple of days, I'll try to answer all your issues. PSS. @RIP21 sorry, I don't use Apollo custom directives. |
Well, I ended up going with the single argument pattern for Vulcan in the end, even if two arguments might be better in some aspects I wanted to stick to the most standard solution. Here's what I decided:
(btw, in case you're wondering |
@SachaG Not too fast ;) Check the rule https://graphql-rules.com/rules/list-filter for lists: - movie(input: { filter, sort, id })
+ movie(filter, sort, id)
- movies(input: { filter, sort, search, skip, limit })
+ movies(filter, sort, search, skip, limit) Even we check existing other Spec eg Relay connection spec, then they are using args on top-level. For now Queries have top-level args, Mutations have |
I know most guides recommend a "single
input
argument" pattern for mutations, but I wanted to get feedback on this alternate pattern. Here's what I mean.Single Argument
The single argument makes sense for
update
mutations whereinput
actually contains multiple nested arguments:But for
create
mutations for example that extra level of nesting doesn't seem useful?Double Argument
Maybe for that reason, Hasura for example uses two arguments,
where
and_set
, and doesn't nest them inside aninput
:Elaborating on this, I would like to suggest that a double argument pattern can pretty much work for any of the basic CRUD queries and mutations. The two arguments being:
selector: { filter: { ... }, sort: { ... } }
: an argument used to select data.data
(a.k.a.movie
,patch
, etc.): contains any data that will be mutated.Unlike the Hasura example where
where
is a top-level argument,selector
would itself containfilter
(a.k.a.where
),sort
(a.k.a.orderBy
), and so on. The idea is to use the same selector input type anywhere you need to select data, whether it's for a query or mutation.Which gives us:
movie(selector)
movies(selector)
createMovie(data)
updateMovie(selector, data)
deleteMovie(selector)
(Note: to that I would even add a third
options
argument that control how the server should behave (e.g. caching behavior). But that's another matter.)Basically, I get why a single argument is better than
n
arguments (as explained here) but I think two arguments is actually better than both of these approaches, since selecting vs mutating data seems to be a good natural distinction that lends itself to this 2-argument approach.EDIT: oh and the
selector
anddata
names are just placeholders, maybe there are better ones.The text was updated successfully, but these errors were encountered: