File: conversions.rb

package info (click to toggle)
ruby-necromancer 0.7.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 308 kB
  • sloc: ruby: 1,578; sh: 4; makefile: 4
file content (129 lines) | stat: -rw-r--r-- 3,167 bytes parent folder | download
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