Class: ElasticGraph::SchemaDefinition::SchemaElements::TypeNamer

Inherits:
Object
  • Object
show all
Defined in:
lib/elastic_graph/schema_definition/schema_elements/type_namer.rb

Overview

Abstraction for generating derived GraphQL type names based on a collection of formats. A default set of formats is included, and overrides can be provided to customize the format we use for naming derived types.

Constant Summary collapse

DEFAULT_FORMATS =

The default formats used for derived GraphQL type names. These formats can be customized by providing ‘derived_type_name_formats` to RakeTasks or Local::RakeTasks.

Returns:

  • (Hash<Symbol, String>)
{
  AggregatedValues: "%{base}AggregatedValues",
  Aggregation: "%{base}Aggregation",
  Connection: "%{base}Connection",
  Edge: "%{base}Edge",
  FieldsListFilterInput: "%{base}FieldsListFilterInput",
  FilterInput: "%{base}FilterInput",
  GroupedBy: "%{base}GroupedBy",
  InputEnum: "%{base}Input",
  ListElementFilterInput: "%{base}ListElementFilterInput",
  ListFilterInput: "%{base}ListFilterInput",
  SortOrder: "%{base}SortOrder",
  SubAggregation: "%{parent_types}%{base}SubAggregation",
  SubAggregations: "%{parent_agg_type}%{field_path}SubAggregations"
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(format_overrides: {}, name_overrides: {}) ⇒ TypeNamer

Initializes a new ‘TypeNamer` with the provided format overrides. The keys in `overrides` must match the keys in `DEFAULT_FORMATS` and the values must have the same placeholders as are present in the default formats.



24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/elastic_graph/schema_definition/schema_elements/type_namer.rb', line 24

def initialize(format_overrides: {}, name_overrides: {})
  @used_names = []
  name_overrides = name_overrides.transform_keys(&:to_s)

  validate_format_overrides(format_overrides)
  validate_name_overrides(name_overrides)

  formats = DEFAULT_FORMATS.merge(format_overrides)
  regexes = formats.transform_values { |format| /\A#{format.gsub(PLACEHOLDER_REGEX, "(\\w+)")}\z/ }
  reverse_overrides = name_overrides.to_h { |k, v| [v, k] }

  super(formats: formats, regexes: regexes, name_overrides: name_overrides, reverse_overrides: reverse_overrides)
end

Class Method Details

.placeholders_in(format) ⇒ Object

Extracts the names of the placeholders from the provided format.



134
135
136
# File 'lib/elastic_graph/schema_definition/schema_elements/type_namer.rb', line 134

def self.placeholders_in(format)
  format.scan(PLACEHOLDER_REGEX).flatten.map(&:to_sym)
end

Instance Method Details

#extract_base_from(name, format:) ⇒ Object

Given a ‘name` that has been generated for the given `format`, extracts the `base` parameter value that was used to generate `name`.

Raises an error if the given ‘format` does not support `base` extraction. (To extract `base`, it’s required that ‘base` is the only placeholder in the format.)

Returns ‘nil` if the given `format` does support `base` extraction but `name` does not match the `format`.



94
95
96
97
98
99
100
# File 'lib/elastic_graph/schema_definition/schema_elements/type_namer.rb', line 94

def extract_base_from(name, format:)
  unless REQUIRED_PLACEHOLDERS.fetch(format) == [:base]
    raise Errors::InvalidArgumentValueError, "The `#{format}` format does not support base extraction."
  end

  regexes.fetch(format).match(name)&.captures&.first
end

#generate_name_for(format_name, **args) ⇒ Object

Generates a derived type name based on the provided format name and arguments. The given arguments must match the placeholders in the format. If the format name is unknown or the arguments are invalid, a ‘Errors::ConfigError` is raised.

Note: this does not apply any configured ‘name_overrides`. It’s up to the caller to apply that when desired.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/elastic_graph/schema_definition/schema_elements/type_namer.rb', line 67

def generate_name_for(format_name, **args)
  format = formats.fetch(format_name) do
    suggestions = FORMAT_SUGGESTER.correct(format_name).map(&:inspect)
    raise Errors::ConfigError, "Unknown format name: #{format_name.inspect}. Possible alternatives: #{suggestions.join(", ")}."
  end

  expected_placeholders = REQUIRED_PLACEHOLDERS.fetch(format_name)
  if (missing_placeholders = expected_placeholders - args.keys).any?
    raise Errors::ConfigError, "The arguments (#{args.inspect}) provided for `#{format_name}` format (#{format.inspect}) omits required key(s): #{missing_placeholders.join(", ")}."
  end

  if (extra_placeholders = args.keys - expected_placeholders).any?
    raise Errors::ConfigError, "The arguments (#{args.inspect}) provided for `#{format_name}` format (#{format.inspect}) contains extra key(s): #{extra_placeholders.join(", ")}."
  end

  format % args
end

#matches_format?(name, format_name) ⇒ Boolean

Indicates if the given ‘name` matches the format for the provided `format_name`.

Note: our formats are not “mutually exclusive”–some names can match more than one format, so the fact that a name matches a format does not guarantee it was generated by that format.

Returns:

  • (Boolean)


108
109
110
# File 'lib/elastic_graph/schema_definition/schema_elements/type_namer.rb', line 108

def matches_format?(name, format_name)
  regexes.fetch(format_name).match?(name)
end

#name_for(standard_name) ⇒ Object

Returns the configured name for the given ‘standard_name`.

By default, the returned name will just be the string form of the given ‘standard_name`, but if the `TypeNamer` was instantiated with an override for the given `standard_name`, that will be returned instead.



45
46
47
48
49
# File 'lib/elastic_graph/schema_definition/schema_elements/type_namer.rb', line 45

def name_for(standard_name)
  string_name = standard_name.to_s
  @used_names << string_name
  name_overrides.fetch(string_name, string_name)
end

#revert_override_for(potentially_overriden_name) ⇒ Object

If the given ‘potentially_overriden_name` is an overridden name, returns the name from before the override was applied. Note: this may not be the true “original” name that ElasticGraph would have have used (e.g. it could still be customized by `formats`) but it will be the name that would be used without any `name_overrides`.



57
58
59
# File 'lib/elastic_graph/schema_definition/schema_elements/type_namer.rb', line 57

def revert_override_for(potentially_overriden_name)
  reverse_overrides.fetch(potentially_overriden_name, potentially_overriden_name)
end

#unused_name_overridesObject

Returns a hash containing the entries of ‘name_overrides` which have not been used. These are likely to be typos, and they can be used to warn the user.



116
117
118
# File 'lib/elastic_graph/schema_definition/schema_elements/type_namer.rb', line 116

def unused_name_overrides
  name_overrides.except(*@used_names.uniq)
end

#used_namesObject

Returns a set containing all names that got passed to ‘name_for`: essentially, these are the candidates for valid name overrides.

Can be used (in conjunction with ‘unused_name_overrides`) to provide suggested alternatives to the user.



127
128
129
# File 'lib/elastic_graph/schema_definition/schema_elements/type_namer.rb', line 127

def used_names
  @used_names.to_set
end