1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 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 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
# frozen_string_literal: true
require_relative "configuration"
require_relative "converter"
require_relative "converters/array"
require_relative "converters/boolean"
require_relative "converters/date_time"
require_relative "converters/hash"
require_relative "converters/numeric"
require_relative "converters/range"
module Necromancer
# Represents the context used to configure various converters
# and facilitate type conversion
#
# @api public
class Conversions
DELIMITER = "->"
# Creates a new conversions map
#
# @example
# conversion = Necromancer::Conversions.new
#
# @api public
def initialize(configuration = Configuration.new, map = {})
@configuration = configuration
@converter_map = map.dup
end
# Load converters
#
# @api private
def load
ArrayConverters.load(self)
BooleanConverters.load(self)
DateTimeConverters.load(self)
HashConverters.load(self)
NumericConverters.load(self)
RangeConverters.load(self)
end
# Retrieve converter for source and target
#
# @param [Object] source
# the source of conversion
#
# @param [Object] target
# the target of conversion
#
# @return [Converter]
# the converter for the source and target
#
# @api public
def [](source, target)
key = "#{source}#{DELIMITER}#{target}"
converter_map[key] ||
converter_map["object#{DELIMITER}#{target}"] ||
raise_no_type_conversion_available(key)
end
alias fetch []
# Register a converter
#
# @example with simple object
# conversions.register NullConverter.new(:array, :array)
#
# @example with block
# conversions.register do |c|
# c.source = :array
# c.target = :array
# c.convert = -> { |val, options| val }
# end
#
# @api public
def register(converter = nil, &block)
converter ||= Converter.create(&block)
key = generate_key(converter)
converter = add_config(converter, @configuration)
return false if converter_map.key?(key)
converter_map[key] = converter
true
end
# Export all the conversions as hash
#
# @return [Hash[String, String]]
#
# @api public
def to_hash
converter_map.dup
end
protected
# Fail with conversion error
#
# @api private
def raise_no_type_conversion_available(key)
raise NoTypeConversionAvailableError, "Conversion '#{key}' unavailable."
end
# @api private
def generate_key(converter)
parts = []
parts << (converter.source ? converter.source.to_s : "none")
parts << (converter.target ? converter.target.to_s : "none")
parts.join(DELIMITER)
end
# Inject config into converter
#
# @api private
def add_config(converter, config)
converter.instance_exec(:"@config") do |var|
instance_variable_set(var, config)
end
converter
end
# Map of type and conversion
#
# @return [Hash]
#
# @api private
attr_reader :converter_map
end # Conversions
end # Necromancer
|