class SmartCore::Initializer::Constructor

@api private @since 0.1.0

Attributes

arguments[R]

@return [Array<Any>]

@api private @since 0.1.0

block[R]

@return [Proc, NilClass]

@api private @since 0.1.0

klass[R]

@return [Class]

@api private @since 0.1.0

options[R]

@return [Hash<Symbol,Any>]

@api private @since 0.1.0

parameters[R]

@return [Array<Any>]

@api private @since 0.1.0

Public Class Methods

new(klass, arguments, block) click to toggle source

@param klass [Class<SmartCore::Initializer>] @param arguments [Array<Any>] @param block [Proc, NilClass] @return [void]

@api private @since 0.1.0

# File lib/smart_core/initializer/constructor.rb, line 15
def initialize(klass, arguments, block)
  @klass = klass
  @arguments = arguments
  @parameters, @options = extract_attributes(arguments)
  @block = block
end

Public Instance Methods

construct() click to toggle source

@return [Any]

@api private @since 0.1.0

# File lib/smart_core/initializer/constructor.rb, line 26
def construct
  allocate_klass_instance.tap do |instance|
    prevent_attribute_insufficiency
    initialize_parameters(instance)
    initialize_options(instance)
    process_original_initializer(instance)
    process_init_extensions(instance)
  end
end

Private Instance Methods

allocate_klass_instance() click to toggle source

@return [Any]

@api private @since 0.1.0

# File lib/smart_core/initializer/constructor.rb, line 108
def allocate_klass_instance
  klass.allocate
end
extract_attributes(arguments) click to toggle source

@param arguments [Array<Any>] @return [Array<Array<Any>,Hash<Symbol,Any>>]

@api private @since 0.1.0

# File lib/smart_core/initializer/constructor.rb, line 179
def extract_attributes(arguments)
  extracted_parameters = []
  extracted_options = {}

  if (
    klass.__options__.size >= 1 &&
    arguments.last.is_a?(Hash) &&
    arguments.last.keys.all? { |key| key.is_a?(Symbol) }
  )
    extracted_parameters = arguments[0..-2]
    extracted_options = arguments.last
  else
    extracted_parameters = arguments
  end

  [extracted_parameters, extracted_options]
end
initialize_options(instance) click to toggle source

@param instance [Any] @return [void]

@api private @since 0.1.0 @version 0.5.1

# File lib/smart_core/initializer/constructor.rb, line 139
def initialize_options(instance)
  klass.__options__.each do |attribute|
    option_value = options.fetch(attribute.name) { attribute.default }

    if !attribute.type.valid?(option_value) && attribute.cast?
      option_value = attribute.type.cast(option_value)
    end

    attribute.validate!(option_value)

    final_value = attribute.finalizer.call(option_value, instance)
    instance.instance_variable_set("@#{attribute.name}", final_value)
  end
end
initialize_parameters(instance) click to toggle source

@param instance [Any] @return [void]

@api private @since 0.1.0 @version 0.5.1

# File lib/smart_core/initializer/constructor.rb, line 118
def initialize_parameters(instance)
  parameter_definitions = klass.__params__.zip(parameters).to_h

  parameter_definitions.each_pair do |attribute, parameter_value|
    if !attribute.type.valid?(parameter_value) && attribute.cast?
      parameter_value = attribute.type.cast(parameter_value)
    end

    attribute.validate!(parameter_value)

    final_value = attribute.finalizer.call(parameter_value, instance)
    instance.instance_variable_set("@#{attribute.name}", final_value)
  end
end
prevent_attribute_insufficiency() click to toggle source

@return [void]

@raise [SmartCore::Initializer::ParameterArgumentError] @raise [SmartCore::Initializer::OptionArgumentError]

@api private @since 0.1.0 @version 0.7.0 rubocop:disable Metrics/AbcSize

# File lib/smart_core/initializer/constructor.rb, line 77
def prevent_attribute_insufficiency
  required_parameter_count = klass.__params__.size

  raise(
    SmartCore::Initializer::ParameterArgumentError,
    "Wrong number of parameters " \
    "(given #{parameters.size}, expected #{required_parameter_count})"
  ) unless parameters.size == required_parameter_count

  required_options = klass.__options__.reject(&:has_default?).map(&:name)
  missing_options  = required_options.reject { |option| options.key?(option) }

  raise(
    SmartCore::Initializer::OptionArgumentError,
    "Missing options: #{missing_options.join(', ')}"
  ) if missing_options.any?

  possible_options = klass.__options__.map(&:name)
  unknown_options  = options.keys - possible_options

  raise(
    SmartCore::Initializer::OptionArgumentError,
    "Unknown options: #{unknown_options.join(', ')}"
  ) if unknown_options.any? && SmartCore::Initializer::Configuration[:strict_options]
end
process_init_extensions(instance) click to toggle source

@param instance [Any] @return [void]

@api private @since 0.1.0

# File lib/smart_core/initializer/constructor.rb, line 168
def process_init_extensions(instance)
  klass.__init_extensions__.each do |extension|
    extension.call(instance)
  end
end
process_original_initializer(instance) click to toggle source

@param instance [Any] @return [void]

@api private @since 0.1.0

# File lib/smart_core/initializer/constructor.rb, line 159
def process_original_initializer(instance)
  instance.send(:initialize, *arguments, &block)
end