app/graphql/mutations/HOWTO Add Mutations.md
Mutations are used for creates/updates/deletes in GraphQL. Creating a mutation is similar to adding a new Type.
Create a new mutation by inheriting from the Mutations::BaseMutation class.
BaseMutation does the following:
errors response field (more on that below).resolve on execution.After creating a new mutation class, add a field for the new mutation to
Types::MutationType.
resolveWhen a mutation is executed, the mutation class's resolve method is executed.
A successful mutation should return a hash containing keys for each response
field in the mutation.
The BaseMutation#errors_for can be used to return AR validation errors, e.g.:
`return errors_for(assignment)`
Mutations generally do not benefit from batch loading. Mutations run sequentially (not in parallel like queries). Because a mutation mutates state, the cache maintained by graphql-batch is also cleared between each mutation. Feel free to use the standard AR association helpers instead of batch loaders when writing a mutation.
There are two classes of errors to consider when working with mutations:
errors response field is for. It
should be considered exceedingly strange to check for validation errors in
resolve (typically you will want to get the validation errors from
Active Record's normal validation stuff).A createFoo and updateFoo mutation will probably be very similar. See
Mutations::CreateAssignment/Mutations::UpdateAssignment for an example of
how to share common code.
A mutation audit log entry is recorded for every output field of a mutation.
Log entries are indexed by the object's asset_string. Sometimes it's
helpful to log against a different object (for example, since PostPolicy
object's are unfamiliar to user's of the audit log, those log entries are
recorded to the associated course/assignment instead. If a mutation has a
response field foo, it can be overridden by defining a foo_log_entry class
method:
def self.foo_log_entry(foo, _context)
foo.bar # <-- will log to `bar_1234` instead of `foo_567'
end
The context passed to that method is the graphql execution context. (This can be useful for retrieving an object that was deleted in a delete mutation--see the code base for examples).
A delete mutation should not return the object that was deleted. Returning the deleted object would cause errors if a user selects fields on the response that are tied to (formerly) associated objects. Instead return something like the deleted object's id.