Class: GraphQL::Schema::FieldExtension

Inherits:
Object
  • Object
show all
Defined in:
lib/graphql/schema/field_extension.rb

Overview

Extend this class to make field-level customizations to resolve behavior.

When a extension is added to a field with extension(MyExtension), a MyExtension instance is created, and its hooks are applied whenever that field is called.

The instance is frozen so that instance variables aren't modified during query execution, which could cause all kinds of issues due to race conditions.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(field:, options:) ⇒ FieldExtension

Called when the extension is mounted with extension(name, options). The instance will be frozen to avoid improper use of state during execution.

Parameters:

  • field (GraphQL::Schema::Field)

    The field where this extension was mounted

  • options (Object)

    The second argument to extension, or {} if nothing was passed.



25
26
27
28
29
30
# File 'lib/graphql/schema/field_extension.rb', line 25

def initialize(field:, options:)
  @field = field
  @options = options || {}
  @added_default_arguments = nil
  apply
end

Instance Attribute Details

#added_default_argumentsArray<Symbol>? (readonly)

Returns default_arguments added, if any were added (otherwise, nil).

Returns:

  • (Array<Symbol>, nil)

    default_arguments added, if any were added (otherwise, nil)



19
20
21
# File 'lib/graphql/schema/field_extension.rb', line 19

def added_default_arguments
  @added_default_arguments
end

#added_extrasObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



117
118
119
# File 'lib/graphql/schema/field_extension.rb', line 117

def added_extras
  @added_extras
end

#fieldGraphQL::Schema::Field (readonly)



13
14
15
# File 'lib/graphql/schema/field_extension.rb', line 13

def field
  @field
end

#optionsObject (readonly)

Returns:



16
17
18
# File 'lib/graphql/schema/field_extension.rb', line 16

def options
  @options
end

Class Method Details

.default_argument(*argument_args, **argument_kwargs) ⇒ Object

See Also:



48
49
50
51
# File 'lib/graphql/schema/field_extension.rb', line 48

def default_argument(*argument_args, **argument_kwargs)
  configs = @own_default_argument_configurations ||= []
  configs << [argument_args, argument_kwargs]
end

.default_argument_configurationsArray(Array, Hash)?

Returns A list of default argument configs, or nil if there aren't any.

Returns:

  • (Array(Array, Hash), nil)

    A list of default argument configs, or nil if there aren't any



34
35
36
37
38
39
40
41
42
43
44
# File 'lib/graphql/schema/field_extension.rb', line 34

def default_argument_configurations
  args = superclass.respond_to?(:default_argument_configurations) ? superclass.default_argument_configurations : nil
  if @own_default_argument_configurations
    if args
      args.concat(@own_default_argument_configurations)
    else
      args = @own_default_argument_configurations.dup
    end
  end
  args
end

.extras(new_extras = nil) ⇒ Array<Symbol>

If configured, these extras will be added to the field if they aren't already present, but removed by from arguments before the field's resolve is called. (The extras will be present for other extensions, though.)

Parameters:

  • new_extras (Array<Symbol>) (defaults to: nil)

    If provided, assign extras used by this extension

Returns:

  • (Array<Symbol>)

    any extras assigned to this extension



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/graphql/schema/field_extension.rb', line 59

def extras(new_extras = nil)
  if new_extras
    @own_extras = new_extras
  end

  inherited_extras = self.superclass.respond_to?(:extras) ? superclass.extras : nil
  if @own_extras
    if inherited_extras
      inherited_extras + @own_extras
    else
      @own_extras
    end
  elsif inherited_extras
    inherited_extras
  else
    GraphQL::EmptyObjects::EMPTY_ARRAY
  end
end

Instance Method Details

#after_definevoid

This method returns an undefined value.

Called after the field's definition block has been executed. (Any arguments from the block are present on field)



88
89
# File 'lib/graphql/schema/field_extension.rb', line 88

def after_define
end

#after_define_applyObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/graphql/schema/field_extension.rb', line 92

def after_define_apply
  after_define
  if (configs = self.class.default_argument_configurations)
    existing_keywords = field.all_argument_definitions.map(&:keyword)
    existing_keywords.uniq!
    @added_default_arguments = []
    configs.each do |config|
      argument_args, argument_kwargs = config
      arg_name = argument_args[0]
      if !existing_keywords.include?(arg_name)
        @added_default_arguments << arg_name
        field.argument(*argument_args, **argument_kwargs)
      end
    end
  end
  if (extras = self.class.extras).any?
    @added_extras = extras - field.extras
    field.extras(@added_extras)
  else
    @added_extras = nil
  end
  freeze
end

#after_resolve(object:, arguments:, context:, value:, memo:) ⇒ Object

Called after #field was resolved, and after any lazy values (like Promises) were synced, but before the value was added to the GraphQL response.

Whatever this hook returns will be used as the return value.

Parameters:

  • object (Object)

    The object the field is being resolved on

  • arguments (Hash)

    Ruby keyword arguments for resolving this field

  • context (Query::Context)

    the context for this query

  • value (Object)

    Whatever the field previously returned

  • memo (Object)

    The third value yielded by #resolve, or nil if there wasn't one

Returns:

  • (Object)

    The return value for this field.



148
149
150
# File 'lib/graphql/schema/field_extension.rb', line 148

def after_resolve(object:, arguments:, context:, value:, memo:)
  value
end

#applyvoid

This method returns an undefined value.

Called when this extension is attached to a field. The field definition may be extended during this method.



82
83
# File 'lib/graphql/schema/field_extension.rb', line 82

def apply
end

#resolve(object:, arguments:, context:) {|object, arguments, memo| ... } ⇒ Object

Called before resolving #field. It should either:

  • yield values to continue execution; OR
  • return something else to shortcut field execution.

Whatever this method returns will be used for execution.

Parameters:

  • object (Object)

    The object the field is being resolved on

  • arguments (Hash)

    Ruby keyword arguments for resolving this field

  • context (Query::Context)

    the context for this query

Yield Parameters:

  • object (Object)

    The object to continue resolving the field on

  • arguments (Hash)

    The keyword arguments to continue resolving with

  • memo (Object)

    Any extension-specific value which will be passed to #after_resolve later

Returns:

  • (Object)

    The return value for this field.



133
134
135
# File 'lib/graphql/schema/field_extension.rb', line 133

def resolve(object:, arguments:, context:)
  yield(object, arguments, nil)
end