Created
September 25, 2019 13:32
-
-
Save bahodge/8958ba90a8b32cb62d018a482f97c4ef to your computer and use it in GitHub Desktop.
Creating a custom mutation return payload with Graphql-Rails
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/graphql/mutations/base_mutation.rb | |
module Mutations | |
# This class is used as a parent for all mutations, and it is the place to have common utilities | |
class BaseMutation < GraphQL::Schema::Mutation | |
null false | |
def enforced_policy | |
... | |
end | |
def set_attributes(args) | |
end | |
def check_permissions(args) | |
end | |
def validate_work(args) | |
end | |
def mutate! | |
end | |
# this method looks at the mutation, | |
# finds all of the defined fields | |
# makes them keys in the hash | |
# attaches their actual values to those keys | |
def build_response_payload | |
response_hash = {} | |
return_fields = self.class.fields | |
return_fields.each do |name, value| | |
if name == 'errors' | |
response_hash[:errors] = [] | |
next | |
end | |
response_hash[name] = self.send(name.to_sym) | |
end | |
response_hash | |
end | |
# I opted for sequentially calling a series of methods | |
# that can be overrided by the child mutation class. | |
def resolve(**args) | |
begin | |
set_attributes(args) | |
check_permissions(args) | |
validate_work(args) | |
mutate! | |
build_response_payload | |
rescue ::Exceptions::PolicyError => e | |
# if an exception is raised, | |
# attach errors to the returning payload | |
payload = build_response_payload | |
payload[:errors] = [{type: 'PERMISSION_ERROR', message: e.message}] | |
payload | |
end | |
end | |
def add_error(new_error: ) | |
errors ||= [] | |
errors << new_error | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/graphql/mutations/clients/create.rb | |
module Mutations | |
class Clients::Create < BaseMutation | |
# Adding the graphql_name will rename the payload from: | |
# 'CreatePayload' - without | |
# 'CreateClientPayload' - with | |
graphql_name "CreateClient" | |
argument :name, String, required: true | |
# These will generate custom payoad that will ultimately return | |
### | |
### "data": { | |
### "createClient": { | |
### "client": { ... }, | |
### "errors": [...] | |
### } | |
### } | |
### | |
field :client, Types::ClientType, null: true | |
field :errors, [Types::ErrorType], null: false | |
attr_accessor :name, :client | |
def set_attributes(args) | |
self.name = args[:name] | |
end | |
def check_permissions(args) | |
enforced_policy.check_policy(test: :is_creator?) | |
end | |
def mutate! | |
self.client = Client.create!(name: self.name) | |
self.client | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// An example mutation using react & gql | |
import gql from 'graphql-tag' | |
export default gql` | |
mutation CREATE_CLIENT($name: String!) { | |
createClient(name: $name) { | |
client { | |
id | |
} | |
errors { | |
type | |
message | |
} | |
} | |
} | |
` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/graphql/types/error_type.rb | |
module Types | |
class ErrorType < BaseObject | |
graphql_name "ErrorType" | |
field :message, String, null: false, description: "A description of the error" | |
field :type, String, null: true, description: "Which input value this error came from" | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { useMutation } from "@apollo/react-hooks"; | |
import CREATE_CLIENT from "../../../graphql/mutations/clients/CreateClientMutation"; | |
const onSubmit = props => { | |
const [createClientMutation] = useMutation(CREATE_CLIENT); | |
// for readabillity i'll destructure 1 level at a time | |
const { data } await createClientMutation({ | |
variables: props.sanitizedValues | |
}); | |
// It returns 'createClient' because that is what I named it in 'app/graphql/types/mutation_type.rb | |
const { createClient } = data | |
const { client, errors } = createClient | |
if (errors.length > 0) return //some error handling procedure | |
// Using react router -> Send to the client page | |
props.history.push(`/clients/${client.id}`); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment