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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf04ea671d5bdbe82a40c6c755e0f975a4326e3f803cc380cbfb513bcb7587d1
4
- data.tar.gz: 14893ca65e6ecb420fac9e4a4783d2ab2267d2b63b492a70c297ca51e66bf711
3
+ metadata.gz: 7c0136727f1cf1e473ac8a517105158a9c927c5988f525b1640ffced32c5a2fd
4
+ data.tar.gz: d26d86cd08edbc33f2f9b8399ef2f7c5aade4b35ca4ea7617dc6a21415b72c9a
5
5
  SHA512:
6
- metadata.gz: c9a89819d1d40b99af14bbc1c0b5df765d5c91ab7c1146f39f8b6dd04796d718251280b6b31b3dc61e14ba413f46d9edb9e7e8a1aa1c308531d20cfdb0c5bb9b
7
- data.tar.gz: b23f67d3df21ca3a01d03c7054502aa0a60d2819717f770db3a30edccdf597b9a9943b7107515e1e454156625c5d1aa3efcd918772b0dcbc5b9b85298ed71fe8
6
+ metadata.gz: 6ec8850e11d3ae4039b748738641bacd19ea3ffe9f437e2d93eb407e9d7e7cb2dcc669116f04f2a175855fbc121bad62228dc6dbd022163d033a52e89af6e8e7
7
+ data.tar.gz: 9ec609fe969d26348c1be54458a79ea24a199085381e82c3bc79d58b5054bb02300759946f520c7b29eb0273e56db290375c791ee4fb2c5fecf10da65954e54b
@@ -9,11 +9,11 @@ matrix:
9
9
  include:
10
10
  - rvm: 2.3.0
11
11
  install:
12
- - gem install bundler --no-ri --no-rdoc
12
+ - gem install bundler --no-document
13
13
  - bundle install
14
14
  - rvm: 2.5.1
15
15
  install:
16
- - gem install bundler --no-ri --no-rdoc
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-rc3
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
@@ -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
- map = { 'First^Name' => :first_name }
252
- converter = ->(column) { map.fetch(column, column.downcase) }
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 that some extra safety.
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
@@ -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', '~> 1.10'
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'
@@ -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 or object that responds to #call
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
- value = if converter_arity == 1
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 converter#call method arity
146
- # @return [Integer] the converter#call method arity
147
- def converter_arity
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 @converter.arity if @converter.respond_to?(:arity)
151
+ return callable.arity if callable.respond_to?(:arity)
150
152
 
151
- @converter.method(:call).arity
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 [Struct] returns an instantiated Struct representing a row
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')
@@ -4,7 +4,7 @@ module HoneyFormat
4
4
  # Gem version
5
5
  VERSION = [
6
6
  MAJOR_VERSION = 0,
7
- MINOR_VERSION = 19,
7
+ MINOR_VERSION = 20,
8
8
  PATCH_VERSION = 0,
9
9
  ].join('.')
10
10
  end
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.19.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: 2018-12-08 00:00:00.000000000 Z
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
- rubyforge_project:
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.