Class: ElasticGraph::SchemaDefinition::SchemaElements::UnionType

Inherits:
Struct
  • Object
show all
Includes:
Mixins::CanBeGraphQLOnly, Mixins::HasDerivedGraphQLTypeCustomizations, Mixins::HasDirectives, Mixins::HasDocumentation, Mixins::HasIndices, Mixins::HasSubtypes, Mixins::SupportsFilteringAndAggregation, Mixins::VerifiesGraphQLName
Defined in:
lib/elastic_graph/schema_definition/schema_elements/union_type.rb

Overview

Defines a [GraphQL union type](graphql.org/learn/schema/#union-types). Use it to define an abstract supertype with one or more concrete subtypes. Each subtype must be an ObjectType, but they do not have to share any fields in common.

Examples:

Define a union type

ElasticGraph.define_schema do |schema|
  schema.object_type "Card" do |t|
    # ...
  end

  schema.object_type "BankAccount" do |t|
    # ...
  end

  schema.object_type "BitcoinWallet" do |t|
    # ...
  end

  schema.union_type "FundingSource" do |t|
    t.subtype "Card"
    t.subtypes "BankAccount", "BitcoinWallet"
  end
end

Instance Attribute Summary collapse

Attributes included from Mixins::HasIndices

#runtime_metadata_overrides

Attributes included from Mixins::HasDocumentation

#doc_comment

Instance Method Summary collapse

Methods included from Mixins::HasDerivedGraphQLTypeCustomizations

#customize_derived_type_fields, #customize_derived_types, #derived_field_customizations_by_name_for_type, #derived_field_customizations_by_type_and_field_name, #derived_type_customizations_by_name, #derived_type_customizations_for_type

Methods included from Mixins::HasSubtypes

#abstract?, #current_sources, #graphql_fields_by_name, #index_field_runtime_metadata_tuples, #indexed?, #indexing_fields_by_name_in_index, #recursively_resolve_subtypes, #to_indexing_field_type

Methods included from Mixins::HasIndices

#abstract?, #derive_indexed_type_fields, #derived_indexed_types, #fields_with_sources, #index, #indexed?, #indices, #plural_root_query_field_name, #root_query_fields, #root_query_fields_customizations, #runtime_metadata, #singular_root_query_field_name

Methods included from Mixins::SupportsFilteringAndAggregation

#derived_graphql_types, #does_not_support?, #has_custom_mapping_type?, #supports?

Methods included from Mixins::HasDirectives

#directive, #directives, #directives_sdl

Methods included from Mixins::HasDocumentation

#append_to_documentation, #derived_documentation, #documentation, #formatted_documentation

Methods included from Mixins::CanBeGraphQLOnly

#graphql_only, #graphql_only?

Methods included from Mixins::VerifiesGraphQLName

verify_name!

Constructor Details

#initialize(schema_def_state, name) ⇒ UnionType

Returns a new instance of UnionType.



63
64
65
66
67
# File 'lib/elastic_graph/schema_definition/schema_elements/union_type.rb', line 63

def initialize(schema_def_state, name)
  super(schema_def_state, schema_def_state.type_ref(name).to_final_form, Set.new) do
    yield self
  end
end

Instance Attribute Details

#schema_def_stateState (readonly)

Returns state of the schema.

Returns:

  • (State)

    state of the schema



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/elastic_graph/schema_definition/schema_elements/union_type.rb', line 51

class UnionType < Struct.new(:schema_def_state, :type_ref, :subtype_refs)
  prepend Mixins::VerifiesGraphQLName
  include Mixins::CanBeGraphQLOnly
  include Mixins::HasDocumentation
  include Mixins::HasDirectives
  include Mixins::SupportsFilteringAndAggregation
  include Mixins::HasIndices
  include Mixins::HasSubtypes
  include Mixins::HasDerivedGraphQLTypeCustomizations
  include Mixins::HasReadableToSAndInspect.new { |t| t.name }

  # @private
  def initialize(schema_def_state, name)
    super(schema_def_state, schema_def_state.type_ref(name).to_final_form, Set.new) do
      yield self
    end
  end

  # @return [String] the name of the union type
  def name
    type_ref.name
  end

  # Defines a subtype of this union type.
  #
  # @param name [String] the name of an object type which is a member of this union type
  # @return [void]
  #
  # @example
  #   ElasticGraph.define_schema do |schema|
  #     schema.object_type "Card" do |t|
  #       # ...
  #     end
  #
  #     schema.union_type "FundingSource" do |t|
  #       t.subtype "Card"
  #     end
  #   end
  def subtype(name)
    type_ref = schema_def_state.type_ref(name.to_s).to_final_form

    if subtype_refs.include?(type_ref)
      raise Errors::SchemaError, "Duplicate subtype on UnionType #{self.name}: #{name}"
    end

    subtype_refs << type_ref
  end

  # Defines multiple subtypes of this union type.
  #
  # @param names [Array<String>] names of object types which are members of this union type
  # @return [void]
  #
  # @example Define a union type
  #   ElasticGraph.define_schema do |schema|
  #     schema.object_type "BankAccount" do |t|
  #       # ...
  #     end
  #
  #     schema.object_type "BitcoinWallet" do |t|
  #       # ...
  #     end
  #
  #     schema.union_type "FundingSource" do |t|
  #       t.subtypes "BankAccount", "BitcoinWallet"
  #     end
  #   end
  def subtypes(*names)
    names.flatten.each { |n| subtype(n) }
  end

  # @return [String] the formatted GraphQL SDL of the union type
  def to_sdl
    if subtype_refs.empty?
      raise Errors::SchemaError, "UnionType type #{name} has no subtypes, but must have at least one."
    end

    "#{formatted_documentation}union #{name} #{directives_sdl(suffix_with: " ")}= #{subtype_refs.map(&:name).to_a.join(" | ")}"
  end

  # @private
  def verify_graphql_correctness!
    # Nothing to verify. `verify_graphql_correctness!` will be called on each subtype automatically.
  end

  # Various things check `mapping_options` on indexed types (usually object types, but can also happen on union types).
  # We need to implement `mapping_options` here to satisfy those method calls, but we will never use custom mapping on
  # a union type so we hardcode it to return nil.
  #
  # @private
  def mapping_options
    {}
  end

  private

  def resolve_subtypes
    subtype_refs.map do |ref|
      ref.as_object_type || raise(
        Errors::SchemaError, "The subtype `#{ref}` of the UnionType `#{name}` is not a defined object type."
      )
    end
  end
end

#subtype_refsObject



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/elastic_graph/schema_definition/schema_elements/union_type.rb', line 51

class UnionType < Struct.new(:schema_def_state, :type_ref, :subtype_refs)
  prepend Mixins::VerifiesGraphQLName
  include Mixins::CanBeGraphQLOnly
  include Mixins::HasDocumentation
  include Mixins::HasDirectives
  include Mixins::SupportsFilteringAndAggregation
  include Mixins::HasIndices
  include Mixins::HasSubtypes
  include Mixins::HasDerivedGraphQLTypeCustomizations
  include Mixins::HasReadableToSAndInspect.new { |t| t.name }

  # @private
  def initialize(schema_def_state, name)
    super(schema_def_state, schema_def_state.type_ref(name).to_final_form, Set.new) do
      yield self
    end
  end

  # @return [String] the name of the union type
  def name
    type_ref.name
  end

  # Defines a subtype of this union type.
  #
  # @param name [String] the name of an object type which is a member of this union type
  # @return [void]
  #
  # @example
  #   ElasticGraph.define_schema do |schema|
  #     schema.object_type "Card" do |t|
  #       # ...
  #     end
  #
  #     schema.union_type "FundingSource" do |t|
  #       t.subtype "Card"
  #     end
  #   end
  def subtype(name)
    type_ref = schema_def_state.type_ref(name.to_s).to_final_form

    if subtype_refs.include?(type_ref)
      raise Errors::SchemaError, "Duplicate subtype on UnionType #{self.name}: #{name}"
    end

    subtype_refs << type_ref
  end

  # Defines multiple subtypes of this union type.
  #
  # @param names [Array<String>] names of object types which are members of this union type
  # @return [void]
  #
  # @example Define a union type
  #   ElasticGraph.define_schema do |schema|
  #     schema.object_type "BankAccount" do |t|
  #       # ...
  #     end
  #
  #     schema.object_type "BitcoinWallet" do |t|
  #       # ...
  #     end
  #
  #     schema.union_type "FundingSource" do |t|
  #       t.subtypes "BankAccount", "BitcoinWallet"
  #     end
  #   end
  def subtypes(*names)
    names.flatten.each { |n| subtype(n) }
  end

  # @return [String] the formatted GraphQL SDL of the union type
  def to_sdl
    if subtype_refs.empty?
      raise Errors::SchemaError, "UnionType type #{name} has no subtypes, but must have at least one."
    end

    "#{formatted_documentation}union #{name} #{directives_sdl(suffix_with: " ")}= #{subtype_refs.map(&:name).to_a.join(" | ")}"
  end

  # @private
  def verify_graphql_correctness!
    # Nothing to verify. `verify_graphql_correctness!` will be called on each subtype automatically.
  end

  # Various things check `mapping_options` on indexed types (usually object types, but can also happen on union types).
  # We need to implement `mapping_options` here to satisfy those method calls, but we will never use custom mapping on
  # a union type so we hardcode it to return nil.
  #
  # @private
  def mapping_options
    {}
  end

  private

  def resolve_subtypes
    subtype_refs.map do |ref|
      ref.as_object_type || raise(
        Errors::SchemaError, "The subtype `#{ref}` of the UnionType `#{name}` is not a defined object type."
      )
    end
  end
end

#type_refObject



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/elastic_graph/schema_definition/schema_elements/union_type.rb', line 51

class UnionType < Struct.new(:schema_def_state, :type_ref, :subtype_refs)
  prepend Mixins::VerifiesGraphQLName
  include Mixins::CanBeGraphQLOnly
  include Mixins::HasDocumentation
  include Mixins::HasDirectives
  include Mixins::SupportsFilteringAndAggregation
  include Mixins::HasIndices
  include Mixins::HasSubtypes
  include Mixins::HasDerivedGraphQLTypeCustomizations
  include Mixins::HasReadableToSAndInspect.new { |t| t.name }

  # @private
  def initialize(schema_def_state, name)
    super(schema_def_state, schema_def_state.type_ref(name).to_final_form, Set.new) do
      yield self
    end
  end

  # @return [String] the name of the union type
  def name
    type_ref.name
  end

  # Defines a subtype of this union type.
  #
  # @param name [String] the name of an object type which is a member of this union type
  # @return [void]
  #
  # @example
  #   ElasticGraph.define_schema do |schema|
  #     schema.object_type "Card" do |t|
  #       # ...
  #     end
  #
  #     schema.union_type "FundingSource" do |t|
  #       t.subtype "Card"
  #     end
  #   end
  def subtype(name)
    type_ref = schema_def_state.type_ref(name.to_s).to_final_form

    if subtype_refs.include?(type_ref)
      raise Errors::SchemaError, "Duplicate subtype on UnionType #{self.name}: #{name}"
    end

    subtype_refs << type_ref
  end

  # Defines multiple subtypes of this union type.
  #
  # @param names [Array<String>] names of object types which are members of this union type
  # @return [void]
  #
  # @example Define a union type
  #   ElasticGraph.define_schema do |schema|
  #     schema.object_type "BankAccount" do |t|
  #       # ...
  #     end
  #
  #     schema.object_type "BitcoinWallet" do |t|
  #       # ...
  #     end
  #
  #     schema.union_type "FundingSource" do |t|
  #       t.subtypes "BankAccount", "BitcoinWallet"
  #     end
  #   end
  def subtypes(*names)
    names.flatten.each { |n| subtype(n) }
  end

  # @return [String] the formatted GraphQL SDL of the union type
  def to_sdl
    if subtype_refs.empty?
      raise Errors::SchemaError, "UnionType type #{name} has no subtypes, but must have at least one."
    end

    "#{formatted_documentation}union #{name} #{directives_sdl(suffix_with: " ")}= #{subtype_refs.map(&:name).to_a.join(" | ")}"
  end

  # @private
  def verify_graphql_correctness!
    # Nothing to verify. `verify_graphql_correctness!` will be called on each subtype automatically.
  end

  # Various things check `mapping_options` on indexed types (usually object types, but can also happen on union types).
  # We need to implement `mapping_options` here to satisfy those method calls, but we will never use custom mapping on
  # a union type so we hardcode it to return nil.
  #
  # @private
  def mapping_options
    {}
  end

  private

  def resolve_subtypes
    subtype_refs.map do |ref|
      ref.as_object_type || raise(
        Errors::SchemaError, "The subtype `#{ref}` of the UnionType `#{name}` is not a defined object type."
      )
    end
  end
end

Instance Method Details

#mapping_optionsObject

Various things check ‘mapping_options` on indexed types (usually object types, but can also happen on union types). We need to implement `mapping_options` here to satisfy those method calls, but we will never use custom mapping on a union type so we hardcode it to return nil.



141
142
143
# File 'lib/elastic_graph/schema_definition/schema_elements/union_type.rb', line 141

def mapping_options
  {}
end

#nameString

Returns the name of the union type.

Returns:

  • (String)

    the name of the union type



70
71
72
# File 'lib/elastic_graph/schema_definition/schema_elements/union_type.rb', line 70

def name
  type_ref.name
end

#subtype(name) ⇒ void

This method returns an undefined value.

Defines a subtype of this union type.

Examples:

ElasticGraph.define_schema do |schema|
  schema.object_type "Card" do |t|
    # ...
  end

  schema.union_type "FundingSource" do |t|
    t.subtype "Card"
  end
end

Parameters:

  • name (String)

    the name of an object type which is a member of this union type



89
90
91
92
93
94
95
96
97
# File 'lib/elastic_graph/schema_definition/schema_elements/union_type.rb', line 89

def subtype(name)
  type_ref = schema_def_state.type_ref(name.to_s).to_final_form

  if subtype_refs.include?(type_ref)
    raise Errors::SchemaError, "Duplicate subtype on UnionType #{self.name}: #{name}"
  end

  subtype_refs << type_ref
end

#subtypes(*names) ⇒ void

This method returns an undefined value.

Defines multiple subtypes of this union type.

Examples:

Define a union type

ElasticGraph.define_schema do |schema|
  schema.object_type "BankAccount" do |t|
    # ...
  end

  schema.object_type "BitcoinWallet" do |t|
    # ...
  end

  schema.union_type "FundingSource" do |t|
    t.subtypes "BankAccount", "BitcoinWallet"
  end
end

Parameters:

  • names (Array<String>)

    names of object types which are members of this union type



118
119
120
# File 'lib/elastic_graph/schema_definition/schema_elements/union_type.rb', line 118

def subtypes(*names)
  names.flatten.each { |n| subtype(n) }
end

#to_sdlString

Returns the formatted GraphQL SDL of the union type.

Returns:

  • (String)

    the formatted GraphQL SDL of the union type



123
124
125
126
127
128
129
# File 'lib/elastic_graph/schema_definition/schema_elements/union_type.rb', line 123

def to_sdl
  if subtype_refs.empty?
    raise Errors::SchemaError, "UnionType type #{name} has no subtypes, but must have at least one."
  end

  "#{formatted_documentation}union #{name} #{directives_sdl(suffix_with: " ")}= #{subtype_refs.map(&:name).to_a.join(" | ")}"
end

#verify_graphql_correctness!Object



132
133
134
# File 'lib/elastic_graph/schema_definition/schema_elements/union_type.rb', line 132

def verify_graphql_correctness!
  # Nothing to verify. `verify_graphql_correctness!` will be called on each subtype automatically.
end