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",
  Highlights: "%{base}Highlights",
  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