honey_format 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/LICENSE.txt +1 -1
- data/README.md +184 -66
- data/bin/benchmark +23 -52
- data/exe/honey_format +20 -59
- data/honey_format.gemspec +2 -2
- data/lib/honey_format.rb +31 -0
- data/lib/honey_format/cli/benchmark_cli.rb +124 -0
- data/lib/honey_format/cli/cli.rb +81 -0
- data/lib/honey_format/cli/result_writer.rb +38 -0
- data/lib/honey_format/configuration.rb +26 -0
- data/lib/honey_format/csv.rb +49 -52
- data/lib/honey_format/errors.rb +6 -2
- data/lib/honey_format/header.rb +27 -29
- data/lib/honey_format/{convert_header_value.rb → header_column_converter.rb} +9 -6
- data/lib/honey_format/matrix.rb +90 -0
- data/lib/honey_format/row.rb +1 -1
- data/lib/honey_format/row_builder.rb +27 -6
- data/lib/honey_format/rows.rb +12 -5
- data/lib/honey_format/value_converter.rb +112 -0
- data/lib/honey_format/version.rb +1 -1
- metadata +12 -6
data/lib/honey_format/errors.rb
CHANGED
@@ -8,8 +8,6 @@ module HoneyFormat
|
|
8
8
|
class MissingHeaderError < HeaderError; end
|
9
9
|
# Raised when header column is missing
|
10
10
|
class MissingHeaderColumnError < HeaderError; end
|
11
|
-
# Raised when a column is not in passed valid columns
|
12
|
-
class UnknownHeaderColumnError < HeaderError; end
|
13
11
|
|
14
12
|
# Row errors
|
15
13
|
# Super class of errors raised when there is a row error
|
@@ -18,6 +16,12 @@ module HoneyFormat
|
|
18
16
|
class EmptyRowColumnsError < RowError; end
|
19
17
|
# Raised when row has more columns than header columns
|
20
18
|
class InvalidRowLengthError < RowError; end
|
19
|
+
|
20
|
+
# Value conversion errors
|
21
|
+
# Raised when value type is unknown
|
22
|
+
class UnknownValueTypeError < ArgumentError; end
|
23
|
+
# Raised when value type already exists
|
24
|
+
class ValueTypeExistsError < ArgumentError; end
|
21
25
|
end
|
22
26
|
|
23
27
|
include Errors
|
data/lib/honey_format/header.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'set'
|
2
2
|
|
3
3
|
module HoneyFormat
|
4
4
|
# Represents a header
|
@@ -8,23 +8,26 @@ module HoneyFormat
|
|
8
8
|
# Instantiate a Header
|
9
9
|
# @return [Header] a new instance of Header.
|
10
10
|
# @param [Array<String>] header array of strings.
|
11
|
-
# @param [
|
12
|
-
# @param converter [#call] header converter that implements a #call method that takes one column (string) argument.
|
11
|
+
# @param converter [#call, Symbol] header converter that implements a #call method that takes one column (string) argument OR symbol for a registered value converter.
|
13
12
|
# @raise [HeaderError] super class of errors raised when there is a CSV header error.
|
14
13
|
# @raise [MissingHeaderColumnError] raised when header is missing
|
15
|
-
# @
|
16
|
-
# @example Instantiate a header with a customer converter
|
14
|
+
# @example Instantiate a header with a custom converter
|
17
15
|
# converter = ->(col) { col == 'username' ? 'handle' : col }
|
18
16
|
# header = HoneyFormat::Header.new(['name', 'username'], converter: converter)
|
19
17
|
# header.to_a # => ['name', 'handle']
|
20
|
-
def initialize(header,
|
18
|
+
def initialize(header, converter: HoneyFormat.header_converter)
|
21
19
|
if header.nil? || header.empty?
|
22
20
|
raise(Errors::MissingHeaderError, "CSV header can't be empty.")
|
23
21
|
end
|
24
22
|
|
25
23
|
@original_header = header
|
26
|
-
@converter = converter
|
27
|
-
|
24
|
+
@converter = if converter.is_a?(Symbol)
|
25
|
+
HoneyFormat.value_converter[converter]
|
26
|
+
else
|
27
|
+
converter
|
28
|
+
end
|
29
|
+
|
30
|
+
@columns = build_columns(@original_header)
|
28
31
|
end
|
29
32
|
|
30
33
|
# @return [Array<String>] the original header
|
@@ -32,6 +35,12 @@ module HoneyFormat
|
|
32
35
|
@original_header
|
33
36
|
end
|
34
37
|
|
38
|
+
# Returns true if columns contains no elements.
|
39
|
+
# @return [true, false] true if columns contains no elements.
|
40
|
+
def empty?
|
41
|
+
@columns.empty?
|
42
|
+
end
|
43
|
+
|
35
44
|
# @yield [row] The given block will be passed for every column.
|
36
45
|
# @yieldparam [Row] a column in the CSV header.
|
37
46
|
# @return [Enumerator]
|
@@ -63,7 +72,7 @@ module HoneyFormat
|
|
63
72
|
# @return [String] CSV-string representation.
|
64
73
|
def to_csv(columns: nil)
|
65
74
|
attributes = if columns
|
66
|
-
self.columns & columns
|
75
|
+
self.columns & columns.map(&:to_sym)
|
67
76
|
else
|
68
77
|
self.columns
|
69
78
|
end
|
@@ -76,24 +85,25 @@ module HoneyFormat
|
|
76
85
|
# Convert original header
|
77
86
|
# @param [Array<String>] header the original header
|
78
87
|
# @return [Array<String>] converted columns
|
79
|
-
def build_columns(header
|
80
|
-
valid = valid.map(&:to_sym)
|
81
|
-
|
88
|
+
def build_columns(header)
|
82
89
|
header.each_with_index.map do |header_column, index|
|
83
90
|
convert_column(header_column, index).tap do |column|
|
84
91
|
maybe_raise_missing_column!(column)
|
85
|
-
maybe_raise_unknown_column!(column, valid)
|
86
92
|
end
|
87
93
|
end
|
88
94
|
end
|
89
95
|
|
90
96
|
# Convert the column value
|
91
|
-
# @param [
|
97
|
+
# @param [String, Symbol] column the CSV header column value
|
92
98
|
# @param [Integer] index the CSV header column index
|
93
|
-
# @return [
|
99
|
+
# @return [Symbol] the converted column
|
94
100
|
def convert_column(column, index)
|
95
|
-
|
96
|
-
|
101
|
+
value = if converter_arity == 1
|
102
|
+
@converter.call(column)
|
103
|
+
else
|
104
|
+
@converter.call(column, index)
|
105
|
+
end
|
106
|
+
value.to_sym
|
97
107
|
end
|
98
108
|
|
99
109
|
# Returns the converter#call method arity
|
@@ -104,18 +114,6 @@ module HoneyFormat
|
|
104
114
|
@converter.method(:call).arity
|
105
115
|
end
|
106
116
|
|
107
|
-
# Raises an error if header column is unknown
|
108
|
-
# @param [Object] column the CSV header column
|
109
|
-
# @param [Array<Symbol, String>] valid CSV columns
|
110
|
-
# @raise [Errors::UnknownHeaderColumnError]
|
111
|
-
def maybe_raise_unknown_column!(column, valid)
|
112
|
-
return if valid.empty?
|
113
|
-
return if valid.include?(column)
|
114
|
-
|
115
|
-
err_msg = "column :#{column} not in #{valid.inspect}"
|
116
|
-
raise(Errors::UnknownHeaderColumnError, err_msg)
|
117
|
-
end
|
118
|
-
|
119
117
|
# Raises an error if header column is missing/empty
|
120
118
|
# @param [Object] column the CSV header column
|
121
119
|
# @raise [Errors::MissingHeaderColumnError]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module HoneyFormat
|
2
2
|
# Header column converter
|
3
|
-
module
|
3
|
+
module HeaderColumnConverter
|
4
4
|
# Replace map
|
5
5
|
REPLACE_MAP = [
|
6
6
|
[/ \(/, '('],
|
@@ -16,13 +16,16 @@ module HoneyFormat
|
|
16
16
|
# Returns converted value and mutates the argument.
|
17
17
|
# @return [Symbol] the cleaned header column.
|
18
18
|
# @param [String] column the string to be cleaned.
|
19
|
-
# @param [Integer] column index.
|
19
|
+
# @param [Integer] index the column index.
|
20
20
|
# @example Convert simple header
|
21
|
-
#
|
21
|
+
# HeaderColumnConverter.call(" User name ") #=> "user_name"
|
22
22
|
# @example Convert complex header
|
23
|
-
#
|
24
|
-
def self.call(column, index)
|
25
|
-
|
23
|
+
# HeaderColumnConverter.call(" First name (user)") #=> :'first_name(user)'
|
24
|
+
def self.call(column, index = nil)
|
25
|
+
if column.nil? || column.empty?
|
26
|
+
raise(ArgumentError, "column and column index can't be blank/nil") unless index
|
27
|
+
return :"column#{index}"
|
28
|
+
end
|
26
29
|
|
27
30
|
column = column.dup
|
28
31
|
column.strip!
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
require 'honey_format/rows'
|
4
|
+
require 'honey_format/header'
|
5
|
+
|
6
|
+
module HoneyFormat
|
7
|
+
# Represents CSV.
|
8
|
+
class Matrix
|
9
|
+
# Instantiate CSV.
|
10
|
+
# @return [CSV] a new instance of Matrix.
|
11
|
+
# @param [Array<Array<String, nil>>] matrix
|
12
|
+
# @param [Array<String>] header optional argument that represents header, required if the matrix lacks a header row.
|
13
|
+
# @param [#call] header_converter converts header columns.
|
14
|
+
# @param [#call] row_builder will be called for each parsed row.
|
15
|
+
# @param type_map [Hash] map of column_name => type conversion to perform.
|
16
|
+
# @raise [HeaderError] super class of errors raised when there is a header error.
|
17
|
+
# @raise [MissingHeaderError] raised when header is missing (empty or nil).
|
18
|
+
# @raise [MissingHeaderColumnError] raised when header column is missing.
|
19
|
+
# @raise [RowError] super class of errors raised when there is a row error.
|
20
|
+
# @raise [EmptyRowColumnsError] raised when row columns are empty.
|
21
|
+
# @raise [InvalidRowLengthError] raised when row has more columns than header columns.
|
22
|
+
# @example
|
23
|
+
# matrix = HoneyFormat::Matrix.new([%w[name id]])
|
24
|
+
# @example With custom header converter
|
25
|
+
# converter = proc { |v| v == 'name' ? 'first_name' : v }
|
26
|
+
# matrix = HoneyFormat::Matrix.new([%w[name id]], header_converter: converter)
|
27
|
+
# matrix.columns # => [:first_name, :id]
|
28
|
+
# @example Handle errors
|
29
|
+
# begin
|
30
|
+
# matrix = HoneyFormat::Matrix.new([%w[name id]])
|
31
|
+
# rescue HoneyFormat::HeaderError => e
|
32
|
+
# puts "header error: #{e.class}, #{e.message}"
|
33
|
+
# rescue HoneyFormat::RowError => e
|
34
|
+
# puts "row error: #{e.class}, #{e.message}"
|
35
|
+
# end
|
36
|
+
def initialize(
|
37
|
+
matrix,
|
38
|
+
header: nil,
|
39
|
+
header_converter: HoneyFormat.header_converter,
|
40
|
+
row_builder: nil,
|
41
|
+
type_map: {}
|
42
|
+
)
|
43
|
+
header_row = header || matrix.shift
|
44
|
+
@header = Header.new(header_row, converter: header_converter)
|
45
|
+
@rows = Rows.new(matrix, columns, builder: row_builder, type_map: type_map)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Original CSV header
|
49
|
+
# @return [Header] object representing the CSV header.
|
50
|
+
def header
|
51
|
+
@header
|
52
|
+
end
|
53
|
+
|
54
|
+
# CSV columns converted from the original CSV header
|
55
|
+
# @return [Array<Symbol>] of column identifiers.
|
56
|
+
def columns
|
57
|
+
@header.to_a
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [Rows] of rows.
|
61
|
+
def rows
|
62
|
+
@rows
|
63
|
+
end
|
64
|
+
|
65
|
+
# @yield [row] The given block will be passed for every row.
|
66
|
+
# @yieldparam [Row] row in the CSV.
|
67
|
+
# @return [Enumerator] If no block is given, an enumerator object will be returned.
|
68
|
+
def each_row
|
69
|
+
return rows.each unless block_given?
|
70
|
+
|
71
|
+
rows.each { |row| yield(row) }
|
72
|
+
end
|
73
|
+
|
74
|
+
# Convert matrix to CSV-string.
|
75
|
+
# @param columns [Array<Symbol>, Set<Symbol>, NilClass] the columns to output, nil means all columns (default: nil)
|
76
|
+
# @yield [row] The given block will be passed for every row - return truthy if you want the row to be included in the output
|
77
|
+
# @yieldparam [Row] row
|
78
|
+
# @return [String] CSV-string representation.
|
79
|
+
# @example with selected columns
|
80
|
+
# matrix.to_csv(columns: [:id, :country])
|
81
|
+
# @example with selected rows
|
82
|
+
# matrix.to_csv { |row| row.country == 'Sweden' }
|
83
|
+
# @example with both selected columns and rows
|
84
|
+
# matrix.to_csv(columns: [:id, :country]) { |row| row.country == 'Sweden' }
|
85
|
+
def to_csv(columns: nil, &block)
|
86
|
+
columns = columns&.map(&:to_sym)
|
87
|
+
@header.to_csv(columns: columns) + @rows.to_csv(columns: columns, &block)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/honey_format/row.rb
CHANGED
@@ -6,24 +6,28 @@ module HoneyFormat
|
|
6
6
|
# Returns a new instance of RowBuilder.
|
7
7
|
# @return [RowBuilder] a new instance of RowBuilder.
|
8
8
|
# @param [Array<Symbol>] columns an array of symbols.
|
9
|
-
# @param builder [#call, #to_csv] optional row builder
|
9
|
+
# @param builder [#call, #to_csv] optional row builder.
|
10
|
+
# @param type_map [Hash] map of column_name => type conversion to perform.
|
10
11
|
# @raise [RowError] super class of errors raised when there is a row error.
|
11
12
|
# @raise [EmptyRowColumnsError] raised when there are no columns.
|
12
13
|
# @raise [InvalidRowLengthError] raised when row has more columns than header columns.
|
13
14
|
# @example Create new row
|
14
15
|
# RowBuilder.new!([:id])
|
15
|
-
def initialize(columns, builder: nil)
|
16
|
+
def initialize(columns, builder: nil, type_map: {})
|
16
17
|
if columns.empty?
|
17
18
|
err_msg = 'Expected array with at least one element, but was empty.'
|
18
19
|
raise(Errors::EmptyRowColumnsError, err_msg)
|
19
20
|
end
|
20
21
|
|
22
|
+
@type_map = type_map
|
23
|
+
@converter = HoneyFormat.value_converter
|
24
|
+
|
21
25
|
@row_klass = Row.new(*columns)
|
22
26
|
@builder = builder
|
23
27
|
@columns = columns
|
24
28
|
end
|
25
29
|
|
26
|
-
# Returns
|
30
|
+
# Returns an object representing the row.
|
27
31
|
# @return [Row, Object] a new instance of built row.
|
28
32
|
# @param row [Array] the row array.
|
29
33
|
# @raise [InvalidRowLengthError] raised when there are more row elements longer than columns
|
@@ -31,9 +35,7 @@ module HoneyFormat
|
|
31
35
|
# r = RowBuilder.new([:id])
|
32
36
|
# r.build(['1']).id #=> '1'
|
33
37
|
def build(row)
|
34
|
-
|
35
|
-
return row unless @builder
|
36
|
-
@builder.call(row)
|
38
|
+
build_row!(row)
|
37
39
|
rescue ArgumentError => e
|
38
40
|
raise unless e.message == 'struct size differs'
|
39
41
|
raise_invalid_row_length!(e, row)
|
@@ -41,6 +43,25 @@ module HoneyFormat
|
|
41
43
|
|
42
44
|
private
|
43
45
|
|
46
|
+
# Returns Struct
|
47
|
+
# @return [Row, Object] a new instance of built row.
|
48
|
+
# @param row [Array] the row array.
|
49
|
+
# @raise [ArgumentError] raised when struct fails to build
|
50
|
+
# @example Build new row
|
51
|
+
# r = RowBuilder.new([:id])
|
52
|
+
# r.build(['1']).id #=> '1'
|
53
|
+
def build_row!(row)
|
54
|
+
row = @row_klass.call(row)
|
55
|
+
|
56
|
+
# Convert values
|
57
|
+
@type_map.each do |column, type|
|
58
|
+
row[column] = @converter.call(row[column], type)
|
59
|
+
end
|
60
|
+
|
61
|
+
return row unless @builder
|
62
|
+
@builder.call(row)
|
63
|
+
end
|
64
|
+
|
44
65
|
# Raises invalid row length error
|
45
66
|
# @param [StandardError] e the raised error
|
46
67
|
# @param [Object] row
|
data/lib/honey_format/rows.rb
CHANGED
@@ -9,15 +9,22 @@ module HoneyFormat
|
|
9
9
|
# Returns array of cleaned strings.
|
10
10
|
# @return [Rows] new instance of Rows.
|
11
11
|
# @param [Array] rows the array of rows.
|
12
|
-
# @param [Array] columns the array of column symbols.
|
12
|
+
# @param [Array<Symbol>] columns the array of column symbols.
|
13
|
+
# @param type_map [Hash] map of column_name => type conversion to perform.
|
13
14
|
# @raise [RowError] super class of errors raised when there is a row error.
|
14
15
|
# @raise [EmptyRowColumnsError] raised when there are no columns.
|
15
16
|
# @raise [InvalidRowLengthError] raised when row has more columns than header columns.
|
16
|
-
def initialize(rows, columns, builder: nil)
|
17
|
-
builder = RowBuilder.new(columns, builder: builder)
|
17
|
+
def initialize(rows, columns, builder: nil, type_map: {})
|
18
|
+
builder = RowBuilder.new(columns, builder: builder, type_map: type_map)
|
18
19
|
@rows = prepare_rows(builder, rows)
|
19
20
|
end
|
20
21
|
|
22
|
+
# Returns true if rows contains no elements.
|
23
|
+
# @return [true, false] true if rows contains no elements.
|
24
|
+
def empty?
|
25
|
+
@rows.empty?
|
26
|
+
end
|
27
|
+
|
21
28
|
# @yield [row] The given block will be passed for every row.
|
22
29
|
# @yieldparam [Row] a row in the CSV file.
|
23
30
|
# @return [Enumerator]
|
@@ -51,7 +58,7 @@ module HoneyFormat
|
|
51
58
|
# csv.to_csv(columns: [:id, :country]) { |row| row.country == 'Sweden' }
|
52
59
|
def to_csv(columns: nil, &block)
|
53
60
|
# Convert columns to Set for performance
|
54
|
-
columns = Set.new(columns) if columns
|
61
|
+
columns = Set.new(columns.map(&:to_sym)) if columns
|
55
62
|
csv_rows = []
|
56
63
|
each do |row|
|
57
64
|
if !block || block.call(row)
|
@@ -66,7 +73,7 @@ module HoneyFormat
|
|
66
73
|
def prepare_rows(builder, rows)
|
67
74
|
built_rows = []
|
68
75
|
rows.each do |row|
|
69
|
-
# ignore empty rows
|
76
|
+
# ignore empty rows
|
70
77
|
next if row.nil? || row.empty? || row == [nil]
|
71
78
|
built_rows << builder.build(row)
|
72
79
|
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'time'
|
3
|
+
require 'set'
|
4
|
+
require 'digest'
|
5
|
+
|
6
|
+
require 'honey_format/header_column_converter'
|
7
|
+
|
8
|
+
module HoneyFormat
|
9
|
+
# Converts values
|
10
|
+
class ValueConverter
|
11
|
+
TRUTHY = Set.new(%w[t T 1 y Y true TRUE]).freeze
|
12
|
+
FALSY = Set.new(%w[f F 0 n N false FALSE]).freeze
|
13
|
+
|
14
|
+
CONVERT_BOOLEAN = lambda { |v|
|
15
|
+
value = v&.downcase
|
16
|
+
if TRUTHY.include?(value)
|
17
|
+
true
|
18
|
+
elsif FALSY.include?(value)
|
19
|
+
false
|
20
|
+
else
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
}
|
24
|
+
|
25
|
+
# Default value converters
|
26
|
+
DEFAULT_CONVERTERS = {
|
27
|
+
# strict variants
|
28
|
+
decimal!: proc { |v| Float(v) },
|
29
|
+
integer!: proc { |v| Integer(v) },
|
30
|
+
date!: proc { |v| Date.parse(v) },
|
31
|
+
datetime!: proc { |v| Time.parse(v) },
|
32
|
+
symbol!: proc { |v| v&.to_sym || raise(ArgumentError, "can't convert nil to symbol") },
|
33
|
+
downcase!: proc { |v| v&.downcase || raise(ArgumentError, "can't convert nil to downcased string") },
|
34
|
+
upcase!: proc { |v| v&.upcase || raise(ArgumentError, "can't convert nil to upcased string") },
|
35
|
+
boolean!: proc { |v|
|
36
|
+
value = CONVERT_BOOLEAN.call(v)
|
37
|
+
raise(ArgumentError, "can't convert #{v} to boolean") if value.nil?
|
38
|
+
value
|
39
|
+
},
|
40
|
+
# safe variants
|
41
|
+
decimal: proc { |v| Float(v) rescue nil },
|
42
|
+
integer: proc { |v| Integer(v) rescue nil },
|
43
|
+
date: proc { |v| Date.parse(v) rescue nil },
|
44
|
+
datetime: proc { |v| Time.parse(v) rescue nil },
|
45
|
+
symbol: proc { |v| v&.to_sym },
|
46
|
+
downcase: proc { |v| v&.downcase },
|
47
|
+
upcase: proc { |v| v&.upcase },
|
48
|
+
boolean: proc { |v| CONVERT_BOOLEAN.call(v) },
|
49
|
+
md5: proc { |v| Digest::MD5.hexdigest(v) if v },
|
50
|
+
nil: proc {},
|
51
|
+
header_column: HeaderColumnConverter,
|
52
|
+
}.freeze
|
53
|
+
|
54
|
+
# Instantiate a value converter
|
55
|
+
def initialize
|
56
|
+
@converters = DEFAULT_CONVERTERS.dup
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns list of registered types
|
60
|
+
# @return [Array<Symbol>] list of registered types
|
61
|
+
def types
|
62
|
+
@converters.keys
|
63
|
+
end
|
64
|
+
|
65
|
+
# Register a value converter
|
66
|
+
# @param [Symbol, String] type the name of the type
|
67
|
+
# @param [#call] converter that responds to #call
|
68
|
+
# @return [ValueConverter] returns self
|
69
|
+
# @raise [ValueTypeExistsError] if type is already registered
|
70
|
+
def register(type, converter)
|
71
|
+
self[type] = converter
|
72
|
+
self
|
73
|
+
end
|
74
|
+
|
75
|
+
# Convert value
|
76
|
+
# @param [Symbol, String] type the name of the type
|
77
|
+
# @param [Object] value to be converted
|
78
|
+
def call(value, type)
|
79
|
+
self[type].call(value)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Register a value converter
|
83
|
+
# @param [Symbol, String] type the name of the type
|
84
|
+
# @param [#call] converter that responds to #call
|
85
|
+
# @return [Object] returns the converter
|
86
|
+
# @raise [ValueTypeExistsError] if type is already registered
|
87
|
+
def []=(type, converter)
|
88
|
+
type = type.to_sym
|
89
|
+
|
90
|
+
if type?(type)
|
91
|
+
raise(Errors::ValueTypeExistsError, "type '#{type}' already exists")
|
92
|
+
end
|
93
|
+
|
94
|
+
@converters[type] = converter
|
95
|
+
end
|
96
|
+
|
97
|
+
# @param [Symbol, String] type the name of the type
|
98
|
+
# @return [Object] returns the converter
|
99
|
+
# @raise [UnknownValueTypeError] if type does not exist
|
100
|
+
def [](type)
|
101
|
+
@converters.fetch(type.to_sym) do
|
102
|
+
raise(Errors::UnknownValueTypeError, "unknown type '#{type}'")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# @param [Symbol, String] type the name of the type
|
107
|
+
# @return [true, false] true if type exists, false otherwise
|
108
|
+
def type?(type)
|
109
|
+
@converters.key?(type.to_sym)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|