Module: ElasticGraph::Support::Config

Defined in:
elasticgraph-support/lib/elastic_graph/support/config.rb

Overview

Provides a standard way to define an ElasticGraph configuration class.

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Class Method Details

.define(*attrs) {|::Data| ... } ⇒ ::Class

Defines a configuration class with the given attributes.

Examples:

Define a configuration class

require "elastic_graph/support/config"

ExampleConfigClass = ElasticGraph::Support::Config.define(:size, :name) do
  json_schema at: "example", optional: false,
    properties: {
      size: {
        description: "Determines the size.",
        examples: [10, 100],
        type: "integer",
        minimum: 1,
      },
      name: {
        description: "Determines the name.",
        examples: ["widget"],
        type: "string",
        minLength: 1
      }
    },
    required: ["size", "name"]
end

Parameters:

  • attrs (::Symbol)

    attribute names

Yields:

  • (::Data)

    the body of the class (similar to ::Data.define)

Returns:

  • (::Class)

    the defined configuration class



46
47
48
49
50
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
# File 'elasticgraph-support/lib/elastic_graph/support/config.rb', line 46

def self.define(*attrs, &block)
  ::Data.define(*attrs) do
    # @implements ::Data
    alias_method :__data_initialize, :initialize
    extend ClassMethods

    # On JRuby 10.0.4.0, `include`-ing a module in a Data.define block causes
    # subclass instances to have nil fields in certain call patterns. Define the
    # instance methods directly instead of using `include InstanceMethods`.
    # See: https://github.com/jruby/jruby/issues/9327

    # Overrides `initialize` to apply JSON schema validation.
    def initialize(**config)
      klass = (_ = self.class) # : ClassMethods[::Data]
      validator = klass.validator
      config = validator.merge_defaults(config)

      if (error = validator.validate_with_error_message(config))
        klass.raise_invalid_config(error)
      end

      config = config.transform_keys(&:to_sym)
      __skip__ = super(**convert_values(**config))
    end

    # Overrides `#with` to bypass the normal JSON schema validation that applies in `#initialize`.
    # This is required so that `config.with(...)` can be used on config classes that use the
    # `convert_values` hook to convert JSON data to some custom Ruby type. The custom Ruby type
    # won't pass JSON schema validation, and if we didn't override `with` then we'd get validation
    # failures due to the converted values failing validation.
    def with(**updates)
      (_ = self.class).new_without_validation(**to_h.merge(updates))
    end

    private

    # Default implementation of a hook that allows config values to be converted during initialization.
    def convert_values(**values)
      values
    end

    public

    class_exec(&(_ = block)) if block
  end
end