class Dry::Core::ClassBuilder

Class for generating more classes

Constants

ParentClassMismatch

Attributes

name[R]
namespace[R]
parent[R]

Public Class Methods

new(name:, parent: nil, namespace: nil) click to toggle source
# File lib/dry/core/class_builder.rb, line 13
def initialize(name:, parent: nil, namespace: nil)
  @name = name
  @namespace = namespace
  @parent = parent || Object
end

Public Instance Methods

call() { |klass| ... } click to toggle source

Generate a class based on options

@example Create anonymous class

builder = Dry::Core::ClassBuilder.new(name: 'MyClass')

klass = builder.call
klass.name # => "MyClass"

@example Create named class

builder = Dry::Core::ClassBuilder.new(name: 'User', namespace: Entities)

klass = builder.call
klass.name # => "Entities::User"
klass.superclass.name # => "Entities::User"
Entities::User # => "Entities::User"
klass.superclass == Entities::User # => true

@return [Class]

# File lib/dry/core/class_builder.rb, line 37
def call
  klass = if namespace
            create_named
          else
            create_anonymous
          end

  yield(klass) if block_given?

  klass
end

Private Instance Methods

create_anonymous() click to toggle source

@api private

# File lib/dry/core/class_builder.rb, line 52
def create_anonymous
  klass = Class.new(parent)
  name = self.name

  klass.singleton_class.class_eval do
    define_method(:name) { name }
    alias_method :inspect, :name
    alias_method :to_s, :name
  end

  klass
end
create_base(namespace, name, parent) click to toggle source

@api private

# File lib/dry/core/class_builder.rb, line 83
def create_base(namespace, name, parent)
  begin
    namespace.const_get(name)
  rescue NameError
  end

  if namespace.const_defined?(name, false)
    existing = namespace.const_get(name)

    unless existing <= parent
      raise ParentClassMismatch, "#{existing.name} must be a subclass of #{parent.name}"
    end

    existing
  else
    klass = Class.new(parent || Object)
    namespace.const_set(name, klass)
    klass
  end
end
create_named() click to toggle source

@api private

# File lib/dry/core/class_builder.rb, line 66
def create_named
  name = self.name
  base = create_base(namespace, name, parent)
  klass = Class.new(base)

  namespace.module_eval do
    remove_const(name)
    const_set(name, klass)

    remove_const(name)
    const_set(name, base)
  end

  klass
end