Result of a delete mutation?
Asked Answered
F

2

34

What should be the result of a delete mutation in Graphql? I'm using the graphql-ruby gem. Here's an example of my mutation, but I'm just not sure what I should be returning as the response.

Mutations::Brands::Delete = GraphQL::Relay::Mutation.define do
  name "DeleteBrand"
  description "Delete a brand"

  input_field :id, types.ID

  # return_field ??

  resolve ->(object, inputs, ctx) {
    brand = Brand.find(inputs[:id])
    brand.destroy
  }
end
Flaccid answered 22/5, 2017 at 19:2 Comment(1)
I think best practice is to return exactly what you deleted so that graphql knows what needs to go away.Discerning
A
7

You can return deleted_id or message. If it is an associated object you can return updated object like below example.

Destroy = GraphQL::Relay::Mutation.define do
name 'DestroyComment'
description 'Delete a comment and return post and deleted comment ID'

# Define input parameters
input_field :id, !types.ID

# Define return parameters
return_field :deletedId, !types.ID
return_field :article, ArticleType
return_field :errors, types.String

resolve ->(_obj, inputs, ctx) {
  comment = Comment.find_by_id(inputs[:id])
  return { errors: 'Comment not found' } if comment.nil?

  article = comment.article
  comment.destroy

  { article: article.reload, deletedId: inputs[:id] }
}

http://tech.eshaiju.in/blog/2017/05/15/graphql-mutation-query-implementation-ruby-on-rails/

Antisana answered 23/5, 2017 at 10:17 Comment(1)
Would this not result in a memory bloat ? @AntisanaBlackpool
R
39

I don't think a clear de facto standard exists as of July, 2017, and I see a lot of differences between implementations (GitHub, Yelp, GraphCool, Shopify).

However, if you look at some of recent GraphQL APIs to come out, there seems to be a common trend. Largely, the input type and response type are specific to the mutation. So for instance, for an updateBrand mutation you might expect an UpdateBrandInput, and return an UpdateBrandPayload response. Notice, the input is not BrandInput, and responding with Brand. Nor would you respond with a scalar boolean (eg. true if successful) or the id of the deleted entity (in the case of a delete mutation). Per this convention, you could have a createBrand mutation, with a CreateBrandInput and a CreateBrandPayload response.

By creating mutation specific input and payload types, you have a lot of flexibility in the fields you expect and respond with. Per deletion, you might have a DeleteBrandPayload response that not only includes shallow (eg. only scalar) fields of the brand, but also other related data (eg. clientMutationId), etc..

To be honest, I think the GraphQL spec gives just enough rope to hang yourself with, so it's smart to look at how some of the big guys are rolling this out.

Rance answered 22/7, 2017 at 23:55 Comment(3)
Funny thing: I was looking for exactly this answer (thank you, it was very useful), and as it happens, the mutations I'm working on are named "createBrand", "updateBrand" and "deleteBrand" :DResnick
Would have been interesting to have the link of some examples of the "big guys" code you're talking about, they've dozens of repositoriesDavis
You can try the GraphQL API from Github here docs.github.com/en/graphql/overview/explorer (you have to sign in), they use this naming: DeleteBrandInput, DeleteBrandPayload.Sigurd
A
7

You can return deleted_id or message. If it is an associated object you can return updated object like below example.

Destroy = GraphQL::Relay::Mutation.define do
name 'DestroyComment'
description 'Delete a comment and return post and deleted comment ID'

# Define input parameters
input_field :id, !types.ID

# Define return parameters
return_field :deletedId, !types.ID
return_field :article, ArticleType
return_field :errors, types.String

resolve ->(_obj, inputs, ctx) {
  comment = Comment.find_by_id(inputs[:id])
  return { errors: 'Comment not found' } if comment.nil?

  article = comment.article
  comment.destroy

  { article: article.reload, deletedId: inputs[:id] }
}

http://tech.eshaiju.in/blog/2017/05/15/graphql-mutation-query-implementation-ruby-on-rails/

Antisana answered 23/5, 2017 at 10:17 Comment(1)
Would this not result in a memory bloat ? @AntisanaBlackpool

© 2022 - 2024 — McMap. All rights reserved.