class GraphQL::Rails::Operations::MutationDefinition

DSL for mutation definition.

Public Class Methods

new(klass) click to toggle source
# File lib/graphql/rails/operations.rb, line 148
def initialize(klass)
  super
  @input = ::GraphQL::InputObjectType.new
  @output = ::GraphQL::ObjectType.new
end

Public Instance Methods

argument(name, type, required = false) click to toggle source
# File lib/graphql/rails/operations.rb, line 164
def argument(name, type, required = false)
  argument = ::GraphQL::Argument.define do
    name Types.to_field_name(name)
    type Types.resolve(type, required == :required)
  end
  @input.arguments[argument.name] = argument
end
field() click to toggle source
# File lib/graphql/rails/operations.rb, line 172
def field
  # Build input object according to mutation specification.
  input = @input
  input.name = "#{@name.to_s.camelize(:upper)}Input"
  input.description = "Generated input type for #{@field.name}"
  input.arguments['clientMutationId'] = ::GraphQL::Argument.define do
    name 'clientMutationId'
    type Types.resolve(::String)
    description 'Unique identifier for client performing mutation'
  end

  # Build compound output object according to mutation specification.
  output = @output
  output.name = "#{@name.to_s.camelize(:upper)}Output"
  output.description = "Generated output type for #{@field.name}"
  output.fields['clientMutationId'] = ::GraphQL::Field.define do
    name 'clientMutationId'
    type Types.resolve(::String)
    description 'Unique identifier for client performing mutation'
  end

  @field.type = output
  @field.arguments['input'] = ::GraphQL::Argument.define do
    name 'input'
    type Types.resolve(input, true)
  end
  @field
end
resolve(&block) click to toggle source
# File lib/graphql/rails/operations.rb, line 201
def resolve(&block)
  @field.resolve = -> (obj, args, ctx) do
    # Instantiate the Operations class with state on this query.
    instance = @klass.new({
      op: :mutation, name: @name, type: @type,
      obj: obj, args: Fields.new(args[:input]), ctx: ctx, context: ctx
    })

    begin
      # Run callbacks for this Operations class.
      instance.run_callbacks(:perform_operation) do
        # Call out to the app-defined resolver.
        result = instance.instance_eval(&block)

        # Transform the result keys to the expected convention.
        unless result.is_a?(::Hash)
          raise 'Mutation must resolve to a Hash result'
        end

        result = result.inject({
          'clientMutationId' => args['clientMutationId']
        }) do |hash, (key, value)|
          hash[Types.to_field_name(key)] = value
          hash
        end
        ::OpenStruct.new(result)
      end
    rescue => e
      # Surface messages from standard errors in GraphQL response.
      ::GraphQL::ExecutionError.new(e.message)
    rescue ::Exception => e
      # Log and genericize other runtime errors.
      Rails.logger.error "Unexpected exception during mutation: #{@name}"
      Rails.logger.exception e
      ::GraphQL::ExecutionError.new('Internal error')
    end
  end
end
type(hash) click to toggle source
# File lib/graphql/rails/operations.rb, line 154
def type(hash)
  hash.each do |name, type|
    field = ::GraphQL::Field.define do
      name Types.to_field_name(name)
      type Types.resolve(type)
    end
    @output.fields[field.name] = field
  end
end