honey_format 0.21.1 → 0.25.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd0d06f453986109809c196cef032b5f60233e165a8d5e029162b26b6cc801b2
4
- data.tar.gz: 8f5a15f42e9f2587bc80b7e88d5c929d74a04ef69bd6be272513ba8fc544a22a
3
+ metadata.gz: bba6cf8014cc6cfa59c8519bbb2448d22800e3f5c3699629fd74132f5b615b82
4
+ data.tar.gz: d1e7dc2ed46e061edd4d473a267c5c1a0296fd58f080e7fecd878341364cb90f
5
5
  SHA512:
6
- metadata.gz: 563e6ba6a8ede49e13d15957c12c247b6e26c981afe25b150d6ae8c6c3dab58929c100341dcc0181790a03eabffca5ddd3ac127cf97fcdb4ac76ef04b01c9839
7
- data.tar.gz: 93a08cb9b2683961e80f8f2bb79f763f05fb1401e112458a6188bf86530233e93f9d397b0ee415e4ce9c8b95ff644485e50dc6b52a2c8381aa4379b0bce0e65a
6
+ metadata.gz: d67aad924dd6d89a56a2e36b1eb84ae2a30e68f71d717fc11c8be960fbf154b0061311105d814b8458b794c6f0a6f93d078fa91efd9c3f3845afcf87c9abfaa4
7
+ data.tar.gz: 2981c007e997cad9e8c58e9cdb4b22654b8f0443ef82345355919068b1bd804d278780808ba361f9077cf1e03bad649060b4474fba99de02a999bc9aea3e7efc
data/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # HEAD
2
2
 
3
+ ## v0.25.0
4
+
5
+ * Add support for adding multiple `Rows` together, `Rows#+`
6
+
7
+ ## v0.24.0
8
+
9
+ * Add support for multiple/chained converters. [PR#69](https://github.com/buren/honey_format/pull/69)
10
+ ```ruby
11
+ csv_string = "Id,Username\n1, BuRen "
12
+ type_map = { username: [:strip, :downcase] }
13
+ csv = HoneyFormat::CSV.new(csv_string, type_map: type_map)
14
+ csv.rows.first.username # => "buren"
15
+ ```
16
+ * Add `strip` and `strip!` converter
17
+
18
+ ## v0.23.0
19
+
20
+ * Add `Rows#columns` method that returns header columns
21
+
22
+ ## v0.22.0
23
+
24
+ * Add `Matrix#type_map` and ignore non-existing column in the type map. [PR#64](https://github.com/buren/honey_format/pull/64). Thank you [@prem-prakash](https://github.com/prem-prakash).
25
+
3
26
  ## v0.21.1
4
27
 
5
28
  * Closes [issue #58](https://github.com/buren/honey_format/issues/58). [PR #62](https://github.com/buren/honey_format/pull/62)
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2018 Jacob Burenstam Linder
3
+ Copyright (c) 2021 Jacob Burenstam Linder
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -107,6 +107,14 @@ csv = HoneyFormat::CSV.new(csv_string, type_map: type_map)
107
107
  csv.rows.first.username # => "BUREN"
108
108
  ```
109
109
 
110
+ Combine multiple converters
111
+ ```ruby
112
+ csv_string = "Id,Username\n1, BuRen "
113
+ type_map = { username: [:strip, :downcase] }
114
+ csv = HoneyFormat::CSV.new(csv_string, type_map: type_map)
115
+ csv.rows.first.username # => "buren"
116
+ ```
117
+
110
118
  Register your own converter
111
119
  ```ruby
112
120
  HoneyFormat.configure do |config|
@@ -315,6 +323,13 @@ user.public_send(:"first^name") # => "Jacob"
315
323
  user['first^name'] # => "Jacob"
316
324
  ```
317
325
 
326
+ Emoji characters
327
+ ```ruby
328
+ csv_string = "😎⛷\nEmoji characters"
329
+ csv = HoneyFormat::CSV.new(csv_string)
330
+ csv.rows.first.😎⛷ # => Emoji characters
331
+ ```
332
+
318
333
  __Errors__
319
334
 
320
335
  > When you need to be extra safe.
@@ -376,6 +391,74 @@ matrix.to_csv # => "name,id\nJACOB,1\n"
376
391
 
377
392
  If you want to see more usage examples check out the [`examples/`](https://github.com/buren/honey_format/tree/master/examples) and [`spec/`](https://github.com/buren/honey_format/tree/master/spec) directories and of course [on RubyDoc](https://www.rubydoc.info/gems/honey_format/).
378
393
 
394
+
395
+ __SQL example__
396
+
397
+ When you want the result as an object, with certain columns converted to objects.
398
+
399
+ ```ruby
400
+ require 'mysql2'
401
+
402
+ class DBClient
403
+ def initialize(host:, username:, password:, port: 3306)
404
+ @client = Mysql2::Client.new(
405
+ host: host,
406
+ username: username,
407
+ password: password,
408
+ port: port
409
+ )
410
+ end
411
+
412
+ def query(sql, type_map: {})
413
+ result = @client.query(sql)
414
+ return if result.first.nil?
415
+
416
+ matrix = HoneyFormat::Matrix.new(
417
+ result.map(&:values),
418
+ header: result.first.keys,
419
+ type_map: type_map
420
+ )
421
+ matrix.rows
422
+ end
423
+ end
424
+ ```
425
+
426
+ Usage example with a fictional "users" database table (schema: `name`, `created_at`)
427
+ ```ruby
428
+ client = DbClient.new(host: '127.0.0.1', username: 'root', password: nil)
429
+ users = client.query(
430
+ 'SELECT * FROM users',
431
+ type_map: { created_at: :datetime! }
432
+ )
433
+ user = users.first
434
+ user.name # => buren
435
+ user.created_at.class # => Time
436
+ ```
437
+
438
+ ## Configuration
439
+
440
+ Configuration is optional
441
+ ```ruby
442
+ HoneyFormat.configure do |config|
443
+ config.header_converter = proc { |column| column.downcase }
444
+ config.delimiter = ";"
445
+ config.row_delimiter = "|"
446
+ config.quote_character = "'"
447
+ config.skip_lines = %r{\A#} # Match all lines that start with "#"
448
+ end
449
+ ```
450
+
451
+ Default configuration values
452
+ ```ruby
453
+ HoneyFormat.configure do |config|
454
+ config.header_converter = HoneyFormat::Registry.new(Converters::DEFAULT)[:header_column]
455
+ config.delimiter = ","
456
+ config.row_delimiter = :auto
457
+ config.quote_character = "\""
458
+ config.skip_lines = nil
459
+ end
460
+ ```
461
+
379
462
  ## CLI
380
463
 
381
464
  > Perfect when you want to get something simple done quickly.
@@ -10,6 +10,9 @@ module HoneyFormat
10
10
  # Convert to upcase or nil
11
11
  ConvertUpcase = proc { |v| v&.upcase }
12
12
 
13
+ # Convert to stripped string
14
+ ConvertStrip = proc { |v| v&.strip }
15
+
13
16
  # Convert to symbol or nil
14
17
  ConvertSymbol = proc { |v| v&.to_sym }
15
18
 
@@ -35,8 +38,13 @@ module HoneyFormat
35
38
  ConvertDowncase.call(v) || raise(ArgumentError, "can't convert nil to downcased string")
36
39
  end
37
40
 
41
+ # Convert to downcase or raise error
42
+ StrictConvertStrip = proc do |v|
43
+ ConvertStrip.call(v) || raise(ArgumentError, "can't convert nil to downcased string")
44
+ end
45
+
38
46
  # Convert to symbol or raise error
39
47
  StrictConvertSymbol = proc do |v|
40
- ConvertSymbol.call(v) || raise(ArgumentError, "can't convert nil to symbol")
48
+ ConvertSymbol.call(v) || raise(ArgumentError, "can't convert nil to stripped string")
41
49
  end
42
50
  end
@@ -20,6 +20,7 @@ module HoneyFormat
20
20
  symbol!: StrictConvertSymbol,
21
21
  downcase!: StrictConvertDowncase,
22
22
  upcase!: StrictConvertUpcase,
23
+ strip!: StrictConvertStrip,
23
24
  boolean!: StrictConvertBoolean,
24
25
  # safe variants
25
26
  decimal: ConvertDecimal,
@@ -31,6 +32,7 @@ module HoneyFormat
31
32
  symbol: ConvertSymbol,
32
33
  downcase: ConvertDowncase,
33
34
  upcase: ConvertUpcase,
35
+ strip: ConvertStrip,
34
36
  boolean: ConvertBoolean,
35
37
  md5: ConvertMD5,
36
38
  hex: ConvertHex,
@@ -51,7 +51,8 @@ module HoneyFormat
51
51
  converter: header_converter,
52
52
  deduplicator: header_deduplicator
53
53
  )
54
- @rows = Rows.new(matrix, columns, builder: row_builder, type_map: type_map)
54
+ @type_map = type_map.select { |key, _v| @header.columns.include?(key) }.to_h
55
+ @rows = Rows.new(matrix, columns, builder: row_builder, type_map: @type_map)
55
56
  end
56
57
 
57
58
  # Original matrix header
@@ -66,6 +67,12 @@ module HoneyFormat
66
67
  @header.to_a
67
68
  end
68
69
 
70
+ # Matrix type map used
71
+ # @return [Hash<Symbol, Symbol>] the type map used.
72
+ def type_map
73
+ @type_map
74
+ end
75
+
69
76
  # Return rows
70
77
  # @return [Rows] rows.
71
78
  def rows
@@ -57,7 +57,11 @@ module HoneyFormat
57
57
 
58
58
  # Convert values
59
59
  @type_map.each do |column, type|
60
- row[column] = @converter.call(row[column], type)
60
+ types = type.respond_to?(:each) ? type : [type]
61
+ value = row[column]
62
+ types.each { |t| value = @converter.call(value, t) }
63
+
64
+ row[column] = value
61
65
  end
62
66
 
63
67
  return row unless @builder
@@ -12,12 +12,24 @@ module HoneyFormat
12
12
  # @param [Array] rows the array of rows.
13
13
  # @param [Array<Symbol>] columns the array of column symbols.
14
14
  # @param type_map [Hash] map of column_name => type conversion to perform.
15
+ # @param pre_built_rows [boolean] whether the rows come pre-built
15
16
  # @raise [RowError] super class of errors raised when there is a row error.
16
17
  # @raise [EmptyRowColumnsError] raised when there are no columns.
17
18
  # @raise [InvalidRowLengthError] raised when row has more columns than header columns.
18
- def initialize(rows, columns, builder: nil, type_map: {})
19
- builder = RowBuilder.new(columns, builder: builder, type_map: type_map)
20
- @rows = prepare_rows(builder, rows)
19
+ def initialize(rows, columns, builder: nil, type_map: {}, pre_built_rows: false)
20
+ @columns = columns
21
+ if pre_built_rows
22
+ @rows = rows
23
+ else
24
+ builder = RowBuilder.new(@columns, builder: builder, type_map: type_map)
25
+ @rows = prepare_rows(builder, rows)
26
+ end
27
+ end
28
+
29
+ # Row columns
30
+ # @return [Array<Symbol>] of column identifiers.
31
+ def columns
32
+ @columns
21
33
  end
22
34
 
23
35
  # Returns true if rows contains no elements.
@@ -26,6 +38,18 @@ module HoneyFormat
26
38
  @rows.empty?
27
39
  end
28
40
 
41
+ # Returns the rows added together.
42
+ # @return [Rows] the two sets of Rows added together.
43
+ # @param [Rows] the other Rows object.
44
+ def +(other)
45
+ if columns != columns.union(other.columns)
46
+ raise ArgumentError, "can't added two sets of rows with different columns"
47
+ end
48
+
49
+ rows = @rows + other.rows_data
50
+ self.class.new(rows, columns, pre_built_rows: true)
51
+ end
52
+
29
53
  # @yield [row] The given block will be passed for every row.
30
54
  # @yieldparam [Row] a row in the CSV file.
31
55
  # @return [Enumerator]
@@ -42,6 +66,7 @@ module HoneyFormat
42
66
 
43
67
  # Return element at given position.
44
68
  # @return [Row] of rows.
69
+ # @param [Integer] the index to return.
45
70
  def [](index)
46
71
  @rows[index]
47
72
  end
@@ -77,6 +102,12 @@ module HoneyFormat
77
102
  csv_rows.join
78
103
  end
79
104
 
105
+ protected
106
+
107
+ def rows_data
108
+ @rows
109
+ end
110
+
80
111
  private
81
112
 
82
113
  def prepare_rows(builder, rows)
@@ -4,7 +4,7 @@ module HoneyFormat
4
4
  # Gem version
5
5
  VERSION = [
6
6
  MAJOR_VERSION = 0,
7
- MINOR_VERSION = 21,
8
- PATCH_VERSION = 1,
7
+ MINOR_VERSION = 25,
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.21.1
4
+ version: 0.25.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: 2020-09-14 00:00:00.000000000 Z
11
+ date: 2021-11-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark-ips
@@ -168,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
168
168
  - !ruby/object:Gem::Version
169
169
  version: '0'
170
170
  requirements: []
171
- rubygems_version: 3.0.3
171
+ rubygems_version: 3.1.4
172
172
  signing_key:
173
173
  specification_version: 4
174
174
  summary: Makes working with CSVs as smooth as honey.