Class: GraphQL::Relay::Mutation

Inherits:
Object
  • Object
show all
Includes:
Define::InstanceDefinable
Defined in:
lib/graphql/relay/mutation.rb,
lib/graphql/relay/mutation/result.rb,
lib/graphql/relay/mutation/resolve.rb,
lib/graphql/relay/mutation/instrumentation.rb

Overview

Define a Relay mutation:

  • give it a name (used for derived inputs & outputs)
  • declare its inputs
  • declare its outputs
  • declare the mutation procedure

resolve should return a hash with a key for each of the return_fields

Inputs may also contain a clientMutationId

Examples:

Updating the name of an item

UpdateNameMutation = GraphQL::Relay::Mutation.define do
  name "UpdateName"

  input_field :name, !types.String
  input_field :itemId, !types.ID

  return_field :item, ItemType

  resolve ->(inputs, ctx) {
    item = Item.find_by_id(inputs[:id])
    item.update(name: inputs[:name])
    {item: item}
  }
end

MutationType = GraphQL::ObjectType.define do
  # The mutation object exposes a field:
  field :updateName, field: UpdateNameMutation.field
end

# Then query it:
query_string = %|
  mutation updateName {
    updateName(input: {itemId: 1, name: "new name", clientMutationId: "1234"}) {
      item { name }
      clientMutationId
  }|

 GraphQL::Query.new(MySchema, query_string).result
 # {"data" => {
 #   "updateName" => {
 #     "item" => { "name" => "new name"},
 #     "clientMutationId" => "1234"
 #   }
 # }}

Using a GraphQL::Function

class UpdateAttributes < GraphQL::Function
  attr_reader :model, :return_as, :arguments

  def initialize(model:, return_as:, attributes:)
    @model = model
    @arguments = {}
    attributes.each do |name, type|
      arg_name = name.to_s
      @arguments[arg_name] = GraphQL::Argument.define(name: arg_name, type: type)
    end
    @arguments["id"] = GraphQL::Argument.define(name: "id", type: !GraphQL::ID_TYPE)
    @return_as = return_as
    @attributes = attributes
  end

  def type
    fn = self
    GraphQL::ObjectType.define do
      name "Update#{fn.model.name}AttributesResponse"
      field :clientMutationId, types.ID
      field fn.return_as.keys[0], fn.return_as.values[0]
    end
  end

  def call(obj, args, ctx)
    record = @model.find(args[:inputs][:id])
    new_values = {}
    @attributes.each { |a| new_values[a] = args[a] }
    record.update(new_values)
    { @return_as => record }
  end
end

UpdateNameMutation = GraphQL::Relay::Mutation.define do
  name "UpdateName"
  function UpdateAttributes.new(model: Item, return_as: { item: ItemType }, attributes: {name: !types.String})
end

Defined Under Namespace

Modules: Instrumentation Classes: Resolve, Result

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Define::InstanceDefinable

#define, #initialize_copy, #metadata, #redefine

Constructor Details

#initializeMutation

Returns a new instance of Mutation.



117
118
119
120
121
# File 'lib/graphql/relay/mutation.rb', line 117

def initialize
  @fields = {}
  @arguments = {}
  @has_generated_return_type = false
end

Instance Attribute Details

#argumentsObject Also known as: input_fields

Returns the value of attribute arguments.



104
105
106
# File 'lib/graphql/relay/mutation.rb', line 104

def arguments
  @arguments
end

#descriptionObject

Returns the value of attribute description.



104
105
106
# File 'lib/graphql/relay/mutation.rb', line 104

def description
  @description
end

#fieldsObject Also known as: return_fields

Returns the value of attribute fields.



104
105
106
# File 'lib/graphql/relay/mutation.rb', line 104

def fields
  @fields
end

#nameObject

Returns the value of attribute name.



104
105
106
# File 'lib/graphql/relay/mutation.rb', line 104

def name
  @name
end

#return_interfacesObject



147
148
149
# File 'lib/graphql/relay/mutation.rb', line 147

def return_interfaces
  @return_interfaces ||= []
end

#return_typeObject



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/graphql/relay/mutation.rb', line 151

def return_type
  @return_type ||= begin
    @has_generated_return_type = true
    relay_mutation = self
    GraphQL::ObjectType.define do
      name("#{relay_mutation.name}Payload")
      description("Autogenerated return type of #{relay_mutation.name}")
      field :clientMutationId, types.String, "A unique identifier for the client performing the mutation.", property: :client_mutation_id
      interfaces relay_mutation.return_interfaces
      relay_mutation.return_fields.each do |name, field_obj|
        field name, field: field_obj
      end
      mutation(relay_mutation)
    end
  end
end

Instance Method Details

#fieldObject



133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/graphql/relay/mutation.rb', line 133

def field
  @field ||= begin
    relay_mutation = self
    field_resolve_proc = @resolve_proc
    GraphQL::Field.define do
      type(relay_mutation.return_type)
      description(relay_mutation.description)
      argument :input, !relay_mutation.input_type
      resolve(field_resolve_proc)
      mutation(relay_mutation)
    end
  end
end

#has_generated_return_type?Boolean

Returns:

  • (Boolean)


123
124
125
126
127
# File 'lib/graphql/relay/mutation.rb', line 123

def has_generated_return_type?
  # Trigger the generation of the return type, if it is dynamically generated:
  return_type
  @has_generated_return_type
end

#input_typeObject



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/graphql/relay/mutation.rb', line 168

def input_type
  @input_type ||= begin
    relay_mutation = self
    input_object_type = GraphQL::InputObjectType.define do
      name("#{relay_mutation.name}Input")
      description("Autogenerated input type of #{relay_mutation.name}")
      input_field :clientMutationId, types.String, "A unique identifier for the client performing the mutation."
      mutation(relay_mutation)
    end
    input_fields.each do |name, arg|
      input_object_type.arguments[name] = arg
    end

    input_object_type
  end
end

#resolve=(new_resolve_proc) ⇒ Object



129
130
131
# File 'lib/graphql/relay/mutation.rb', line 129

def resolve=(new_resolve_proc)
  @resolve_proc = new_resolve_proc
end

#result_classObject



185
186
187
# File 'lib/graphql/relay/mutation.rb', line 185

def result_class
  @result_class ||= Result.define_subclass(self)
end