Class: ElasticGraph::SchemaDefinition::SchemaElements::TypeReference
- Inherits:
-
Object
- Object
- ElasticGraph::SchemaDefinition::SchemaElements::TypeReference
- Extended by:
- Forwardable
- Defined in:
- lib/elastic_graph/schema_definition/schema_elements/type_reference.rb
Overview
Represents a reference to a type. This is basically just a name of a type, with the ability to resolve it to an actual type object on demand. In addition, we provide some useful logic that is based entirely on the type name.
This is necessary because GraphQL does not require that types are defined before they are referenced. (And also you can have circular type dependencies). Therefore, we need to use a reference to a type initially, and can later resolve it to a concrete type object as needed.
Constant Summary collapse
- STATIC_FORMAT_NAME_BY_CATEGORY =
Most of ElasticGraph’s derived GraphQL types have a static suffix (e.g. the full type name is source_type + suffix). This is a map of all of these.
TypeNamer::REQUIRED_PLACEHOLDERS.filter_map do |format_name, placeholders| if placeholders == [:base] as_snake_case = SchemaArtifacts::RuntimeMetadata::SchemaElementNamesDefinition::SnakeCaseConverter .normalize_case(format_name.to_s) .delete_prefix("_") [as_snake_case.to_sym, format_name] end end.to_h
Instance Method Summary collapse
-
#as_aggregation_sub_aggregations(parent_doc_types: [fully_unwrapped.name], field_path: []) ⇒ Object
Generates the type name used for a ‘sub_aggregations` field.
-
#as_object_type ⇒ Object
Returns the ‘ObjectType`, `UnionType` or `InterfaceType` object to which this type name refers, if it is the name of one of those kinds of types.
- #as_parent_aggregation(parent_doc_types:) ⇒ Object
-
#as_static_derived_type(category) ⇒ Object
Builds a ‘TypeReference` for a statically named derived type for the given `category.
-
#as_sub_aggregation(parent_doc_types:) ⇒ Object
Generates the type name used for a sub-aggregation.
- #boolean? ⇒ Boolean
- #enum? ⇒ Boolean
-
#fully_unwrapped ⇒ Object
Extracts the type without any non-null or list wrappings it has.
-
#json_schema_layers ⇒ Object
Returns all the JSON schema array/nullable layers of a type, from outermost to innermost.
-
#leaf? ⇒ Boolean
Returns ‘true` if this is known to be a scalar type or enum type.
-
#list? ⇒ Boolean
Returns ‘true` if this is a list type.
- #list_element_filter_input? ⇒ Boolean
- #list_filter_input? ⇒ Boolean
-
#non_null? ⇒ Boolean
Returns ‘true` if this is a non-null type.
-
#object? ⇒ Boolean
Returns ‘true` if this is known to be an object type of some sort (including interface types, union types, and proper object types).
- #resolved ⇒ Object
-
#scalar_type_needing_grouped_by_object? ⇒ Boolean
Generally speaking, scalar types have ‘grouped_by` fields which are scalars of the same types, and object types have `grouped_by` fields which are special `[object_type]GroupedBy` types.
-
#to_final_form(as_input: false) ⇒ Object
Converts the TypeReference to its final form (i.e. the from that will be used in rendered schema artifacts).
- #to_s ⇒ Object
-
#unwrap_list ⇒ Object
Removes the list wrapping if this is a list.
-
#unwrap_non_null ⇒ Object
Removes any non-null wrappings the type has.
- #unwrapped_name ⇒ Object
-
#with_reverted_override ⇒ Object
Returns a new ‘TypeReference` with any type name overrides reverted (to provide the “original” type name).
- #wrap_non_null ⇒ Object
Instance Method Details
#as_aggregation_sub_aggregations(parent_doc_types: [fully_unwrapped.name], field_path: []) ⇒ Object
Generates the type name used for a ‘sub_aggregations` field. A `sub_aggregations` field is available alongside `grouped_by`, `count`, and `aggregated_values` on an aggregation or sub-aggregation node. This type is used in two situations:
-
It is used directly under ‘nodes`/`edges { node }` on an Aggregation or SubAggregation. It provides access to each of the sub-aggregations that are available in that context.
-
It is used underneath that ‘SubAggregations` object for single object fields which have fields under them that are sub-aggregatable.
The fields (and types of those fields) used for one of these types is contextual based on what the parent doc types are (so that we can offer sub-aggregations of the parent doc types!) and the field path (for the 2nd case).
252 253 254 255 256 257 258 259 260 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 252 def as_aggregation_sub_aggregations(parent_doc_types: [fully_unwrapped.name], field_path: []) field_part = field_path.map { |f| to_title_case(f.name) }.join renamed_with_same_wrappings(type_namer.generate_name_for( :SubAggregations, parent_agg_type: parent_aggregation_type(parent_doc_types), field_path: field_part )) end |
#as_object_type ⇒ Object
Returns the ‘ObjectType`, `UnionType` or `InterfaceType` object to which this type name refers, if it is the name of one of those kinds of types.
Ignores any non-null wrapping on the type, if there is one.
60 61 62 63 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 60 def as_object_type type = _ = unwrap_non_null.resolved type if type.respond_to?(:graphql_fields_by_name) end |
#as_parent_aggregation(parent_doc_types:) ⇒ Object
262 263 264 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 262 def as_parent_aggregation(parent_doc_types:) schema_def_state.type_ref(parent_aggregation_type(parent_doc_types)) end |
#as_static_derived_type(category) ⇒ Object
Builds a ‘TypeReference` for a statically named derived type for the given `category.
In addition, a dynamic method ‘as_` is also provided (defined further below).
217 218 219 220 221 222 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 217 def as_static_derived_type(category) renamed_with_same_wrappings(type_namer.generate_name_for( STATIC_FORMAT_NAME_BY_CATEGORY.fetch(category), base: fully_unwrapped.name )) end |
#as_sub_aggregation(parent_doc_types:) ⇒ Object
Generates the type name used for a sub-aggregation. This type has ‘grouped_by`, `aggregated_values`, `count` and `sub_aggregations` sub-fields to expose the different bits of aggregation functionality.
The type name is based both on the type reference name and on the set of ‘parent_doc_types` that exist above it. The `parent_doc_types` are used in the name because we plan to offer different sub-aggregations under it based on where it is in the document structure. A type which is `nested` at multiple levels in different document contexts needs separate types generated for each case so that we can offer the correct contextual sub-aggregations that can be offered for each case.
232 233 234 235 236 237 238 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 232 def as_sub_aggregation(parent_doc_types:) renamed_with_same_wrappings(type_namer.generate_name_for( :SubAggregation, base: fully_unwrapped.name, parent_types: parent_doc_types.join )) end |
#boolean? ⇒ Boolean
138 139 140 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 138 def boolean? name == "Boolean" end |
#enum? ⇒ Boolean
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 95 def enum? return unwrap_non_null.enum? if non_null? if (resolved_type = resolved) return resolved_type.is_a?(EnumType) end # For derived GraphQL types, the name usually implies what kind of type it is. # The derived types get generated last, so this prediate may be called before the # type has been defined. case schema_kind_implied_by_name when :object false when :enum true else # If we can't determine the type from the name, just raise an error. raise Errors::SchemaError, "Type `#{name}` cannot be resolved. Is it misspelled?" end end |
#fully_unwrapped ⇒ Object
Extracts the type without any non-null or list wrappings it has.
35 36 37 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 35 def fully_unwrapped schema_def_state.type_ref(unwrapped_name) end |
#json_schema_layers ⇒ Object
Returns all the JSON schema array/nullable layers of a type, from outermost to innermost. For example, [[Int]] will return [:nullable, :array, :nullable, :array, :nullable]
171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 171 def json_schema_layers @json_schema_layers ||= begin layers, inner_type = peel_json_schema_layers_once if layers.empty? || inner_type == self layers else layers + inner_type.json_schema_layers end end end |
#leaf? ⇒ Boolean
Returns ‘true` if this is known to be a scalar type or enum type. Returns `false` if this is known to be an object type or list type of any sort.
Raises an error if it cannot be determined either from the name or by resolving the type.
Ignores any non-null wrapping on the type, if there is one.
122 123 124 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 122 def leaf? !list? && !object? end |
#list? ⇒ Boolean
Returns ‘true` if this is a list type.
Ignores any non-null wrapping on the type, if there is one.
129 130 131 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 129 def list? name.start_with?("[") end |
#list_element_filter_input? ⇒ Boolean
278 279 280 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 278 def list_element_filter_input? matches_format_of?(:list_element_filter_input) end |
#list_filter_input? ⇒ Boolean
274 275 276 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 274 def list_filter_input? matches_format_of?(:list_filter_input) end |
#non_null? ⇒ Boolean
Returns ‘true` if this is a non-null type.
134 135 136 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 134 def non_null? name.end_with?("!") end |
#object? ⇒ Boolean
Returns ‘true` if this is known to be an object type of some sort (including interface types, union types, and proper object types).
Returns ‘false` if this is known to be a leaf type of some sort (either a scalar or enum). Returns `false` if this is a list type (either a list of objects or leafs).
Raises an error if it cannot be determined either from the name or by resolving the type.
Ignores any non-null wrapping on the type, if there is one.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 74 def object? return unwrap_non_null.object? if non_null? if (resolved_type = resolved) return resolved_type.respond_to?(:graphql_fields_by_name) end # For derived GraphQL types, the name usually implies what kind of type it is. # The derived types get generated last, so this prediate may be called before the # type has been defined. case schema_kind_implied_by_name when :object true when :enum false else # If we can't determine the type from the name, just raise an error. raise Errors::SchemaError, "Type `#{name}` cannot be resolved. Is it misspelled?" end end |
#resolved ⇒ Object
146 147 148 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 146 def resolved schema_def_state.types_by_name[name] end |
#scalar_type_needing_grouped_by_object? ⇒ Boolean
Generally speaking, scalar types have ‘grouped_by` fields which are scalars of the same types, and object types have `grouped_by` fields which are special `[object_type]GroupedBy` types.
…except for some special cases (Date and DateTime), which this predicate detects.
160 161 162 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 160 def scalar_type_needing_grouped_by_object? %w[Date DateTime].include?(type_namer.revert_override_for(name)) end |
#to_final_form(as_input: false) ⇒ Object
Converts the TypeReference to its final form (i.e. the from that will be used in rendered schema artifacts). This handles multiple bits of type name customization based on the configured ‘type_name_overrides` and `derived_type_name_formats` settings (via the `TypeNamer`):
-
If the ‘as_input` is `true` and this is a reference to an enum type, converts to the `InputEnum` format.
-
If there is a configured name override that applies to this type, uses it.
201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 201 def to_final_form(as_input: false) unwrapped = fully_unwrapped inner_name = type_namer.name_for(unwrapped.name) if as_input && schema_def_state.type_ref(inner_name).enum? inner_name = type_namer.name_for( type_namer.generate_name_for(:InputEnum, base: inner_name) ) end renamed_with_same_wrappings(inner_name) end |
#to_s ⇒ Object
142 143 144 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 142 def to_s name end |
#unwrap_list ⇒ Object
Removes the list wrapping if this is a list.
If the outer wrapping is non-null, unwraps that as well.
52 53 54 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 52 def unwrap_list schema_def_state.type_ref(unwrap_non_null.name.delete_prefix("[").delete_suffix("]")) end |
#unwrap_non_null ⇒ Object
Removes any non-null wrappings the type has.
40 41 42 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 40 def unwrap_non_null schema_def_state.type_ref(name.delete_suffix("!")) end |
#unwrapped_name ⇒ Object
150 151 152 153 154 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 150 def unwrapped_name name .sub(/\A\[+/, "") # strip `[` characters from the start: https://rubular.com/r/tHVBBQkQUMMVVz .sub(/[\]!]+\z/, "") # strip `]` and `!` characters from the end: https://rubular.com/r/pC8C0i7EpvHDbf end |
#with_reverted_override ⇒ Object
Returns a new ‘TypeReference` with any type name overrides reverted (to provide the “original” type name).
165 166 167 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 165 def with_reverted_override schema_def_state.type_ref(type_namer.revert_override_for(name)) end |
#wrap_non_null ⇒ Object
44 45 46 47 |
# File 'lib/elastic_graph/schema_definition/schema_elements/type_reference.rb', line 44 def wrap_non_null return self if non_null? schema_def_state.type_ref("#{name}!") end |