honey_format 0.19.0 → 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -3
- data/CHANGELOG.md +12 -0
- data/README.md +23 -8
- data/honey_format.gemspec +1 -1
- data/lib/honey_format/csv.rb +6 -1
- data/lib/honey_format/matrix/header.rb +40 -14
- data/lib/honey_format/matrix/row.rb +1 -1
- data/lib/honey_format/version.rb +1 -1
- metadata +11 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c0136727f1cf1e473ac8a517105158a9c927c5988f525b1640ffced32c5a2fd
|
4
|
+
data.tar.gz: d26d86cd08edbc33f2f9b8399ef2f7c5aade4b35ca4ea7617dc6a21415b72c9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ec8850e11d3ae4039b748738641bacd19ea3ffe9f437e2d93eb407e9d7e7cb2dcc669116f04f2a175855fbc121bad62228dc6dbd022163d033a52e89af6e8e7
|
7
|
+
data.tar.gz: 9ec609fe969d26348c1be54458a79ea24a199085381e82c3bc79d58b5054bb02300759946f520c7b29eb0273e56db290375c791ee4fb2c5fecf10da65954e54b
|
data/.travis.yml
CHANGED
@@ -9,11 +9,11 @@ matrix:
|
|
9
9
|
include:
|
10
10
|
- rvm: 2.3.0
|
11
11
|
install:
|
12
|
-
- gem install bundler --no-
|
12
|
+
- gem install bundler --no-document
|
13
13
|
- bundle install
|
14
14
|
- rvm: 2.5.1
|
15
15
|
install:
|
16
|
-
- gem install bundler --no-
|
16
|
+
- gem install bundler --no-document
|
17
17
|
- bundle install
|
18
18
|
- rvm: 2.6.0-preview3
|
19
19
|
install:
|
@@ -21,7 +21,7 @@ matrix:
|
|
21
21
|
- name: TruffleRuby
|
22
22
|
rvm: system
|
23
23
|
install:
|
24
|
-
- export TRUFFLERUBY_VERSION=1.0.0-
|
24
|
+
- export TRUFFLERUBY_VERSION=1.0.0-rc10
|
25
25
|
- curl -L https://github.com/oracle/truffleruby/releases/download/vm-$TRUFFLERUBY_VERSION/truffleruby-$TRUFFLERUBY_VERSION-linux-amd64.tar.gz | tar xz
|
26
26
|
- export PATH="$PWD/truffleruby-$TRUFFLERUBY_VERSION-linux-amd64/bin:$PATH"
|
27
27
|
- gem install bundler -v 1.16.6 --no-ri --no-rdoc
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# HEAD
|
2
2
|
|
3
|
+
## v0.20.0
|
4
|
+
|
5
|
+
* Support additional header variant, pass hash with `String => Symbol` and/or `String => #call` (callable object). Unmapped keys are converted using the default header converter.
|
6
|
+
```ruby
|
7
|
+
converter = {
|
8
|
+
'First name' => :first_name,
|
9
|
+
'Last name' => -> { :surname }
|
10
|
+
}
|
11
|
+
csv = HoneyFormat::CSV.new(csv_string, header_converter: converter)
|
12
|
+
```
|
13
|
+
* Add `encoding` option to `CSV`
|
14
|
+
|
3
15
|
## v0.19.0
|
4
16
|
|
5
17
|
* Add `method_name` as alias for `header_column` converter
|
data/README.md
CHANGED
@@ -27,8 +27,8 @@ Id,Username,Email
|
|
27
27
|
2,jacob,jacob@example.com
|
28
28
|
CSV
|
29
29
|
csv = HoneyFormat::CSV.new(csv_string, type_map: { id: :integer })
|
30
|
-
csv.columns # => [:id, :username]
|
31
|
-
csv.rows # => [#<Row id=1, username="buren">]
|
30
|
+
csv.columns # => [:id, :username, :email]
|
31
|
+
csv.rows # => [#<Row id=1, username="buren", email="buren@example.com">, #<Row id=2, username="jacob", email="jacob@example.com">]
|
32
32
|
user = csv.rows.first
|
33
33
|
user.id # => 1
|
34
34
|
user.username # => "buren"
|
@@ -248,21 +248,36 @@ csv.columns # => [:ID, :USERNAME]
|
|
248
248
|
|
249
249
|
Pass your own header converter
|
250
250
|
```ruby
|
251
|
-
|
252
|
-
|
251
|
+
# unmapped keys use the default header converter,
|
252
|
+
# mix simple key => value mapping with key => proc
|
253
|
+
converter = {
|
254
|
+
'First^Name' => :first_name,
|
255
|
+
'Username' => -> { :handle }
|
256
|
+
}
|
253
257
|
|
254
|
-
csv_string = "ID,First^Name\n1,Jacob"
|
258
|
+
csv_string = "ID,Username,First^Name\n1,buren,Jacob"
|
255
259
|
user = HoneyFormat::CSV.new(csv_string, header_converter: converter).rows.first
|
256
260
|
user.first_name # => "Jacob"
|
261
|
+
user.handle # => "buren"
|
257
262
|
user.id # => "1"
|
263
|
+
|
264
|
+
# you can also pass a proc or any callable object
|
265
|
+
converter = Class.new do
|
266
|
+
define_singleton_method(:call) { |value, index| "#{value}#{index}" }
|
267
|
+
end
|
268
|
+
# or
|
269
|
+
converter = ->(value, index) { "#{value}#{index}" }
|
270
|
+
user = HoneyFormat::CSV.new(csv_string, header_converter: converter)
|
258
271
|
```
|
259
272
|
|
260
|
-
Missing header values
|
273
|
+
Missing header values are automatically set and deduplicated
|
261
274
|
```ruby
|
262
|
-
csv_string = "first,,third\nval0,val1,val2"
|
275
|
+
csv_string = "first,,third,third\nval0,val1,val2,val3"
|
263
276
|
csv = HoneyFormat::CSV.new(csv_string)
|
264
277
|
user = csv.rows.first
|
265
278
|
user.column1 # => "val1"
|
279
|
+
user.third # => "val2"
|
280
|
+
user.third1 # => "val3"
|
266
281
|
```
|
267
282
|
|
268
283
|
Duplicated header values
|
@@ -302,7 +317,7 @@ user['first^name'] # => "Jacob"
|
|
302
317
|
|
303
318
|
__Errors__
|
304
319
|
|
305
|
-
> When you need
|
320
|
+
> When you need to be extra safe.
|
306
321
|
|
307
322
|
If you want to there are some errors you can rescue
|
308
323
|
```ruby
|
data/honey_format.gemspec
CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.required_ruby_version = '>= 2.3.0'
|
24
24
|
|
25
25
|
spec.add_development_dependency 'benchmark-ips'
|
26
|
-
spec.add_development_dependency 'bundler', '
|
26
|
+
spec.add_development_dependency 'bundler', '> 1.10', '< 3'
|
27
27
|
spec.add_development_dependency 'byebug'
|
28
28
|
spec.add_development_dependency 'rake', '~> 10.0'
|
29
29
|
spec.add_development_dependency 'rspec'
|
data/lib/honey_format/csv.rb
CHANGED
@@ -19,6 +19,7 @@ module HoneyFormat
|
|
19
19
|
# @param header_deduplicator [#call] deduplicates header columns.
|
20
20
|
# @param row_builder [#call] will be called for each parsed row.
|
21
21
|
# @param type_map [Hash] map of column_name => type conversion to perform.
|
22
|
+
# @param encoding [String] CSV encoding (for example "BOM|UTF-16LE:UTF-8").
|
22
23
|
# @param skip_lines [Regexp, String]
|
23
24
|
# Regexp for determining wheter a line is a comment. See CSV skip_lines option.
|
24
25
|
# @raise [HeaderError] super class of errors raised when there is a CSV header error.
|
@@ -46,6 +47,8 @@ module HoneyFormat
|
|
46
47
|
# @example Skip lines all lines starting with '#'
|
47
48
|
# csv = HoneyFormat::CSV.new("name,id\n# some comment\njacob,1", skip_lines: '#')
|
48
49
|
# csv.rows.length # => 1
|
50
|
+
# @example CSV encoding
|
51
|
+
# csv = HoneyFormat::CSV.new(csv_string, encoding: "BOM|UTF-16LE:UTF-8")
|
49
52
|
# @see Matrix#new
|
50
53
|
def initialize(
|
51
54
|
csv,
|
@@ -56,6 +59,7 @@ module HoneyFormat
|
|
56
59
|
header_converter: HoneyFormat.header_converter,
|
57
60
|
header_deduplicator: HoneyFormat.config.header_deduplicator,
|
58
61
|
row_builder: nil,
|
62
|
+
encoding: nil,
|
59
63
|
type_map: {},
|
60
64
|
skip_lines: HoneyFormat.config.skip_lines
|
61
65
|
)
|
@@ -65,7 +69,8 @@ module HoneyFormat
|
|
65
69
|
row_sep: row_delimiter,
|
66
70
|
quote_char: quote_character,
|
67
71
|
skip_blanks: true,
|
68
|
-
skip_lines: skip_lines
|
72
|
+
skip_lines: skip_lines,
|
73
|
+
encoding: encoding
|
69
74
|
)
|
70
75
|
super(
|
71
76
|
csv,
|
@@ -10,10 +10,11 @@ module HoneyFormat
|
|
10
10
|
# Instantiate a Header
|
11
11
|
# @return [Header] a new instance of Header.
|
12
12
|
# @param [Array<String>] header array of strings.
|
13
|
-
# @param converter [#call, Symbol]
|
13
|
+
# @param converter [#call, Symbol, Hash]
|
14
14
|
# header converter that implements a #call method
|
15
15
|
# that takes one column (string) argument OR symbol for a registered
|
16
|
-
# converter registry
|
16
|
+
# converter registry OR a hash mapped to a symbol or something that responds
|
17
|
+
# to #call.
|
17
18
|
# @param deduplicator [#call, Symbol]
|
18
19
|
# header deduplicator that implements a #call method
|
19
20
|
# that takes columns Array<String> argument OR symbol for a registered
|
@@ -93,7 +94,7 @@ module HoneyFormat
|
|
93
94
|
private
|
94
95
|
|
95
96
|
# Set the header converter
|
96
|
-
# @param [Symbol, #call] symbol to known converter
|
97
|
+
# @param [Hash, Symbol, #call] symbol to known converter, object that responds to #call or Hash
|
97
98
|
# @return [nil]
|
98
99
|
def converter=(object)
|
99
100
|
if object.is_a?(Symbol)
|
@@ -101,6 +102,11 @@ module HoneyFormat
|
|
101
102
|
return
|
102
103
|
end
|
103
104
|
|
105
|
+
if object.is_a?(Hash)
|
106
|
+
@converter = hash_converter(object)
|
107
|
+
return
|
108
|
+
end
|
109
|
+
|
104
110
|
@converter = object
|
105
111
|
end
|
106
112
|
|
@@ -134,21 +140,17 @@ module HoneyFormat
|
|
134
140
|
# @param [Integer] index the CSV header column index
|
135
141
|
# @return [Symbol] the converted column
|
136
142
|
def convert_column(column, index)
|
137
|
-
|
138
|
-
@converter.call(column)
|
139
|
-
else
|
140
|
-
@converter.call(column, index)
|
141
|
-
end
|
142
|
-
value.to_sym
|
143
|
+
call_column_builder(@converter, column, index)&.to_sym
|
143
144
|
end
|
144
145
|
|
145
|
-
# Returns the
|
146
|
-
# @
|
147
|
-
|
146
|
+
# Returns the callable object method arity
|
147
|
+
# @param [#arity, #call] callable thing that responds to #call and maybe #arity
|
148
|
+
# @return [Integer] the method arity
|
149
|
+
def callable_arity(callable)
|
148
150
|
# procs and lambdas respond to #arity
|
149
|
-
return
|
151
|
+
return callable.arity if callable.respond_to?(:arity)
|
150
152
|
|
151
|
-
|
153
|
+
callable.method(:call).arity
|
152
154
|
end
|
153
155
|
|
154
156
|
# Raises an error if header column is missing/empty
|
@@ -164,5 +166,29 @@ module HoneyFormat
|
|
164
166
|
]
|
165
167
|
raise(Errors::MissingHeaderColumnError, parts.join(' '))
|
166
168
|
end
|
169
|
+
|
170
|
+
def hash_converter(hash)
|
171
|
+
lambda { |value, index|
|
172
|
+
# support strings and symbol keys interchangeably
|
173
|
+
column = hash.fetch(value) do
|
174
|
+
key = value.respond_to?(:to_sym) ? value.to_sym : value
|
175
|
+
# if column is unmapped use the default header converter
|
176
|
+
hash.fetch(key) { HoneyFormat.header_converter.call(value, index) }
|
177
|
+
end
|
178
|
+
|
179
|
+
# The hash can contain mixed values, Symbol and procs
|
180
|
+
if column.respond_to?(:call)
|
181
|
+
column = call_column_builder(column, value, index)
|
182
|
+
end
|
183
|
+
|
184
|
+
column&.to_sym
|
185
|
+
}
|
186
|
+
end
|
187
|
+
|
188
|
+
def call_column_builder(callable, value, index)
|
189
|
+
return callable.call if callable_arity(callable).zero?
|
190
|
+
return callable.call(value) if callable_arity(callable) == 1
|
191
|
+
callable.call(value, index)
|
192
|
+
end
|
167
193
|
end
|
168
194
|
end
|
@@ -4,7 +4,7 @@ module HoneyFormat
|
|
4
4
|
# Default row builder
|
5
5
|
class Row < Struct
|
6
6
|
# Create a row
|
7
|
-
# @return [
|
7
|
+
# @return [Row] returns an instantiated Row
|
8
8
|
# @example
|
9
9
|
# row_klass = Row.new(:id, :username)
|
10
10
|
# row = row_klass.call('1', 'buren')
|
data/lib/honey_format/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: honey_format
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.20.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jacob Burenstam
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-12-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: benchmark-ips
|
@@ -28,16 +28,22 @@ dependencies:
|
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.10'
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '3'
|
34
37
|
type: :development
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
37
40
|
requirements:
|
38
|
-
- - "
|
41
|
+
- - ">"
|
39
42
|
- !ruby/object:Gem::Version
|
40
43
|
version: '1.10'
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '3'
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
48
|
name: byebug
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -162,8 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
162
168
|
- !ruby/object:Gem::Version
|
163
169
|
version: '0'
|
164
170
|
requirements: []
|
165
|
-
|
166
|
-
rubygems_version: 2.7.6
|
171
|
+
rubygems_version: 3.0.3
|
167
172
|
signing_key:
|
168
173
|
specification_version: 4
|
169
174
|
summary: Makes working with CSVs as smooth as honey.
|