Class: JSON::SchemaDsl::Builder

Inherits:
Object
  • Object
show all
Defined in:
lib/json/schema_dsl/builder.rb

Overview

TODO:

Refactor class and remove rubocop exception

Builders are used to build entity-structs. They handle building this raw data so it can then be given to the renderers which modify the structure to be valid json-schema.

Each type has an associated Builder that is a dynamically generated class. Since entity-structs are immutable, the builder updates the struct and keeps track of the latest version of the struct.

Entity definitions can mostly be treated as data input while most of the logic of building the entity tree resides in the builders. rubocop:disable Metrics/ClassLength

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(inner, scope: nil) ⇒ Builder

Returns a new instance of Builder.

Parameters:

  • inner (JSON::SchemaDsl::Entity)

    The struct that the builder is supposed to update and build up.

  • scope (Object) (defaults to: nil)

    The scope is used for as a fallback for helper methods.

See Also:



139
140
141
142
# File 'lib/json/schema_dsl/builder.rb', line 139

def initialize(inner, scope: nil)
  @inner = inner
  @scope = scope
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args, &block) ⇒ Object (private)



167
168
169
170
171
172
173
174
# File 'lib/json/schema_dsl/builder.rb', line 167

def method_missing(meth, *args, &block)
  return super unless scope&.respond_to?(meth, true)

  maybe_child = scope.send(meth, *args, &block)
  maybe_child.respond_to?(:render) &&
    add_child(maybe_child)
  maybe_child
end

Class Attribute Details

.inner_classObject

Returns the value of attribute inner_class.



18
19
20
# File 'lib/json/schema_dsl/builder.rb', line 18

def inner_class
  @inner_class
end

Instance Attribute Details

#innerObject (readonly)

Returns the value of attribute inner.



131
132
133
# File 'lib/json/schema_dsl/builder.rb', line 131

def inner
  @inner
end

#scopeObject (readonly)

Returns the value of attribute scope.



131
132
133
# File 'lib/json/schema_dsl/builder.rb', line 131

def scope
  @scope
end

Class Method Details

.[](klass) ⇒ Object

Returns A new builder class that subclasses JSON::SchemaDsl::Builder.

Parameters:

  • klass (Class)

    A class that is a subclass of Entity.

Returns:

Raises:

  • (ArgumentError)


22
23
24
25
26
# File 'lib/json/schema_dsl/builder.rb', line 22

def [](klass)
  raise ArgumentError, "#{klass} is not a struct." unless klass < AstNode

  registered_builders[klass] ||= klass.builder
end

.add_defaults_for(type, defaults) ⇒ Hash<Symbol, Hash>

Adds new defaults for the given type.

Parameters:

  • type (Symbol)

    The type symbol for the type. Usually the name underscored and symbolized. I.e. Object => ‘:object`.

  • defaults (Hash<Symbol, Object>)

    New defaults that will be merged to the existing ones.

Returns:

  • (Hash<Symbol, Hash>)

See Also:

  • #type_defaults


56
57
58
59
60
61
62
# File 'lib/json/schema_dsl/builder.rb', line 56

def add_defaults_for(type, defaults)
  if type_defaults[type].empty?
    type_defaults[type] = type_defaults[type].merge(defaults)
  else
    type_defaults[type].merge!(defaults)
  end
end

.build(name = nil, scope: nil, **attributes, &block) ⇒ Object

Instantiates a new builder instance with a corresponding entity and applies the attributes and block to construct a complete entity.

Parameters:

  • name (#to_s) (defaults to: nil)

    The name of the new entity. This is important for the entity to be added to properties later. Usually is the name of a property or the pattern for a pattern property.

  • scope (Object) (defaults to: nil)

    The scope will be used as a fallback to evaluate the block. If there are any methods that the block does not understand, the scope will be called instead.

  • attributes (Hash)

    The initial attributes that the entity will start with before the block is applied.

  • block (Proc)

    Will be evaluated in the context of the builder. Should contain setter methods.



77
78
79
80
81
82
83
# File 'lib/json/schema_dsl/builder.rb', line 77

def build(name = nil, scope: nil, **attributes, &block)
  type     = (attributes[:type] || inner_class.infer_type)&.to_sym
  defaults = ::JSON::SchemaDsl::Builder
             .type_defaults[type].merge(name: name, type: type)
  builder  = new(inner_class.new(defaults), scope: scope)
  Docile.dsl_eval(builder, &config_block(attributes, &block))
end

.class_nameObject

nodoc



91
92
93
# File 'lib/json/schema_dsl/builder.rb', line 91

def class_name
  name || inner_class.name + 'Builder'
end

.define_builder(klass) ⇒ Object

Returns A new builder class that subclasses JSON::SchemaDsl::Builder.

Parameters:

  • klass (Class)

    A class that is a subclass of Entity.

Returns:

See Also:

  • #[]


109
110
111
112
113
114
115
116
117
118
# File 'lib/json/schema_dsl/builder.rb', line 109

def define_builder(klass)
  Class.new(self) do
    self.inner_class = klass
    klass.schema.keys.map(&:name).each do |name|
      define_method(name) do |*args, **opts, &block|
        set(name, *args, **opts, &block)
      end
    end
  end
end

.define_builder_method(type) ⇒ Object

Defines a new method for the builder instance that mirrors the dsl method

for the given type.

Parameters:

  • type (Class)

    A class that is a subclass of Entity.



98
99
100
101
102
103
104
# File 'lib/json/schema_dsl/builder.rb', line 98

def define_builder_method(type)
  type_param = type.type_method_name || 'entity'
  define_method(type_param) do |name = nil, **attributes, &block|
    new_child = build_struct(type, name, **attributes, &block)
    add_child(new_child)
  end
end

.inspectObject

nodoc



86
87
88
# File 'lib/json/schema_dsl/builder.rb', line 86

def inspect
  "#<#{class_name} inner_class=#{inner_class}>"
end

.registered_buildersArray<JSON::SchemaDsl::Builder>

Returns All builders that have been registered so far. Usually builders get automatically registered when the associated type is registered.

Returns:

  • (Array<JSON::SchemaDsl::Builder>)

    All builders that have been registered so far. Usually builders get automatically registered when the associated type is registered.



31
32
33
# File 'lib/json/schema_dsl/builder.rb', line 31

def registered_builders
  @registered_builders ||= {}
end

.reset_type_defaults!Hash<Symbol, Hash>

Clears the registered type defaults and returns an empty hash.

Returns:

  • (Hash<Symbol, Hash>)

See Also:

  • #type_defaults


45
46
47
# File 'lib/json/schema_dsl/builder.rb', line 45

def reset_type_defaults!
  type_defaults.clear
end

.type_defaultsHash<Symbol, Hash>

Returns Defaults that are applied when a new struct of a given type is contsructed. The type symbol is the key and the defaults the value of this hash.

Returns:

  • (Hash<Symbol, Hash>)

    Defaults that are applied when a new struct of a given type is contsructed. The type symbol is the key and the defaults the value of this hash.



38
39
40
# File 'lib/json/schema_dsl/builder.rb', line 38

def type_defaults
  @type_defaults ||= Hash.new { {} }
end

Instance Method Details

#renderObject

Renders the given tree structure into a hash. Note that this hash still has symbol keys.

The scope used for the render is the same as the builder.

See Also:



147
148
149
# File 'lib/json/schema_dsl/builder.rb', line 147

def render
  ::JSON::SchemaDsl::Renderer.new(inner, scope).render
end