Module: ElasticGraph::SchemaDefinition::Mixins::ImplementsInterfaces
- Included in:
- SchemaElements::InterfaceType, SchemaElements::ObjectType
- Defined in:
- lib/elastic_graph/schema_definition/mixins/implements_interfaces.rb
Overview
Mixin for types that can implement interfaces (SchemaElements::ObjectType and SchemaElements::InterfaceType).
Instance Method Summary collapse
-
#implemented_interfaces ⇒ Array<SchemaElements::TypeReference>
List of type references for the interface types implemented by this type.
-
#implements(*interface_names) ⇒ void
Declares that the current type implements the specified interface, making the current type a subtype of the interface.
-
#to_sdl {|SchemaElements::Argument| ... } ⇒ String
SDL string of the type.
-
#verify_graphql_correctness! ⇒ void
Called after the schema definition is complete, before dumping artifacts.
Instance Method Details
#implemented_interfaces ⇒ Array<SchemaElements::TypeReference>
Returns list of type references for the interface types implemented by this type.
54 55 56 |
# File 'lib/elastic_graph/schema_definition/mixins/implements_interfaces.rb', line 54 def implemented_interfaces @implemented_interfaces ||= [] end |
#implements(*interface_names) ⇒ void
This method returns an undefined value.
Declares that the current type implements the specified interface, making the current type a subtype of the interface. The current type must define all of the fields of the named interface, with the exact same field types.
43 44 45 46 47 48 49 50 51 |
# File 'lib/elastic_graph/schema_definition/mixins/implements_interfaces.rb', line 43 def implements(*interface_names) interface_refs = interface_names.map do |interface_name| schema_def_state.type_ref(interface_name).to_final_form.tap do |interface_ref| schema_def_state.implementations_by_interface_ref[interface_ref] << self end end implemented_interfaces.concat(interface_refs) end |
#to_sdl {|SchemaElements::Argument| ... } ⇒ String
Returns SDL string of the type.
109 110 111 112 113 114 115 116 117 118 |
# File 'lib/elastic_graph/schema_definition/mixins/implements_interfaces.rb', line 109 def to_sdl(&field_arg_selector) name_section = if implemented_interfaces.empty? name else "#{name} implements #{implemented_interfaces.join(" & ")}" end generate_sdl(name_section: name_section, &field_arg_selector) end |
#verify_graphql_correctness! ⇒ void
This method returns an undefined value.
Called after the schema definition is complete, before dumping artifacts. Here we validate the correctness of interface implementations. We defer it until this time to not require the interface and fields to be defined before the ‘implements` call.
Note that the GraphQL gem on its own supports a form of “interface inheritance”: if declaring that an object type implements an interface, and the object type is missing one or more of the interface fields, the GraphQL gem dynamically adds the missing interface fields to the object type (at least, that’s the result I noted when dumping the GraphQL SDL after trying that!). However, we cannot allow that, because our schema definition is used to generate non-GrapQL artifacts (e.g. the JSON schema and the index mapping), and all the artifacts must agree on the fields. Therefore, we use this method to verify that the object type fully implements the specified interfaces.
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 |
# File 'lib/elastic_graph/schema_definition/mixins/implements_interfaces.rb', line 73 def verify_graphql_correctness! = implemented_interfaces.filter_map do |interface_ref| interface = interface_ref.resolved case interface when SchemaElements::InterfaceType differences = (_ = interface).interface_fields_by_name.values.filter_map do |interface_field| my_field_sdl = graphql_fields_by_name[interface_field.name]&.to_sdl(type_structure_only: true) interface_field_sdl = interface_field.to_sdl(type_structure_only: true) if my_field_sdl.nil? "missing `#{interface_field.name}`" elsif my_field_sdl != interface_field_sdl "`#{interface_field_sdl.strip}` vs `#{my_field_sdl.strip}`" end end unless differences.empty? "Type `#{name}` does not correctly implement interface `#{interface_ref}` " \ "due to field differences: #{differences.join("; ")}." end when nil "Type `#{name}` cannot implement `#{interface_ref}` because `#{interface_ref}` is not defined." else "Type `#{name}` cannot implement `#{interface_ref}` because `#{interface_ref}` is not an interface." end end unless .empty? raise Errors::SchemaError, .join("\n\n") end end |