Sha256: 27c9f436cfc632f030784e064a60a8cff8e349523832525e0b9bb81c4a888683

Contents?: true

Size: 1.57 KB

Versions: 4

Compression:

Stored size: 1.57 KB

Contents

#
# Prepare nested data type from a block
#
# @example
#   option :foo do
#     option :bar
#     option :qux
#   end
#
module Dry::Initializer::Dispatchers::BuildNestedType
  extend self

  # rubocop: disable Metrics/ParameterLists
  def call(parent:, source:, target:, type: nil, block: nil, **options)
    check_certainty!(source, type, block)
    check_name!(target, block)
    type ||= build_nested_type(parent, target, block)
    { parent: parent, source: source, target: target, type: type, **options }
  end
  # rubocop: enable Metrics/ParameterLists

  private

  def check_certainty!(source, type, block)
    return unless block
    return unless type

    raise ArgumentError, <<~MESSAGE
      You should define coercer of values of argument '#{source}'
      either though the parameter/option, or via nested block, but not the both.
    MESSAGE
  end

  def check_name!(name, block)
    return unless block
    return unless name[/^_|__|_$/]

    raise ArgumentError, <<~MESSAGE
      The name of the argument '#{name}' cannot be used for nested struct.
      A proper name can use underscores _ to divide alphanumeric parts only.
    MESSAGE
  end

  def build_nested_type(parent, name, block)
    return unless block

    klass_name = full_name(parent, name)
    build_struct(klass_name, block)
  end

  def full_name(parent, name)
    "::#{parent.name}::#{name.to_s.split("_").compact.map(&:capitalize).join}"
  end

  def build_struct(klass_name, block)
    eval "class #{klass_name} < Dry::Initializer::Struct; end"
    const_get(klass_name).tap { |klass| klass.class_eval(&block) }
  end
end

Version data entries

4 entries across 4 versions & 1 rubygems

Version Path
dry-initializer-3.0.4 lib/dry/initializer/dispatchers/build_nested_type.rb
dry-initializer-3.0.3 lib/dry/initializer/dispatchers/build_nested_type.rb
dry-initializer-3.0.2 lib/dry/initializer/dispatchers/build_nested_type.rb
dry-initializer-3.0.1 lib/dry/initializer/dispatchers/build_nested_type.rb