Result of a delete mutation?

2019-04-27 03:28发布

问题:

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

回答1:

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/



回答2:

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.