honey_format 0.20.0 → 0.24.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: 7c0136727f1cf1e473ac8a517105158a9c927c5988f525b1640ffced32c5a2fd
4
- data.tar.gz: d26d86cd08edbc33f2f9b8399ef2f7c5aade4b35ca4ea7617dc6a21415b72c9a
3
+ metadata.gz: 4e7b05a5cbde9ef4df67f043ff78e75c545563faa02333c57c97f70f1adec0f9
4
+ data.tar.gz: 91275865eabfd283c22ef0507a76b0c433d64a36c2ab68d92501548b982a00c8
5
5
  SHA512:
6
- metadata.gz: 6ec8850e11d3ae4039b748738641bacd19ea3ffe9f437e2d93eb407e9d7e7cb2dcc669116f04f2a175855fbc121bad62228dc6dbd022163d033a52e89af6e8e7
7
- data.tar.gz: 9ec609fe969d26348c1be54458a79ea24a199085381e82c3bc79d58b5054bb02300759946f520c7b29eb0273e56db290375c791ee4fb2c5fecf10da65954e54b
6
+ metadata.gz: c5904b276f295163855c1d74f7afa27568572e50583ec54532e571f70eb59ce06648e60a0e0d29806289d7126b8d0a9351acdd746967c247db03004cec3c4356
7
+ data.tar.gz: e498be3c0e31e594cc42d2186404d367564111d70d2fffbe0011d0ea208e5f217ff8416061f12cbdff5137b3075e1f09d857b2dd189d785b865381d02c429d07
data/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # HEAD
2
2
 
3
+ ## v0.24.0
4
+
5
+ * Add support for multiple/chained converters. [PR#69](https://github.com/buren/honey_format/pull/69)
6
+ ```ruby
7
+ csv_string = "Id,Username\n1, BuRen "
8
+ type_map = { username: [:strip, :downcase] }
9
+ csv = HoneyFormat::CSV.new(csv_string, type_map: type_map)
10
+ csv.rows.first.username # => "buren"
11
+ ```
12
+ * Add `strip` and `strip!` converter
13
+
14
+ ## v0.23.0
15
+
16
+ * Add `Rows#columns` method that returns header columns
17
+
18
+ ## v0.22.0
19
+
20
+ * 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).
21
+
22
+ ## v0.21.1
23
+
24
+ * Closes [issue #58](https://github.com/buren/honey_format/issues/58). [PR #62](https://github.com/buren/honey_format/pull/62)
25
+
26
+ ## v0.21.0
27
+
28
+ * Add `Rows#[]` method
29
+
3
30
  ## v0.20.0
4
31
 
5
32
  * Support additional header variant, pass hash with `String => Symbol` and/or `String => #call` (callable object). Unmapped keys are converted using the default header converter.
data/README.md CHANGED
@@ -91,7 +91,7 @@ __Type converters__
91
91
 
92
92
  > Type converters are great if you want to convert column values, like numbers and dates.
93
93
 
94
- There are a few default type converters
94
+ There are a bunch of [default type converters](https://github.com/buren/honey_format/blob/master/lib/honey_format/converters/converters.rb)
95
95
  ```ruby
96
96
  csv_string = "Id,Username\n1,buren"
97
97
  type_map = { id: :integer }
@@ -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|
@@ -139,7 +147,7 @@ Default converter names
139
147
  HoneyFormat.config.default_converters.keys
140
148
  ```
141
149
 
142
- See [`Configuration#default_converters`](https://github.com/buren/honey_format/blob/master/lib/honey_format/configuration.rb#L99) for a complete list of the default ones.
150
+ See [`Converters::DEFAULT`](https://github.com/buren/honey_format/blob/master/lib/honey_format/converters.rb) for a complete list of the default converter names.
143
151
 
144
152
  __Row builder__
145
153
 
@@ -376,6 +384,50 @@ matrix.to_csv # => "name,id\nJACOB,1\n"
376
384
 
377
385
  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
386
 
387
+
388
+ __SQL example__
389
+
390
+ When you want the result as an object, with certain columns converted to objects.
391
+
392
+ ```ruby
393
+ require 'mysql2'
394
+
395
+ class DBClient
396
+ def initialize(host:, username:, password:, port: 3306)
397
+ @client = Mysql2::Client.new(
398
+ host: host,
399
+ username: username,
400
+ password: password,
401
+ port: port
402
+ )
403
+ end
404
+
405
+ def query(sql, type_map: {})
406
+ result = @client.query(sql)
407
+ return if result.first.nil?
408
+
409
+ matrix = HoneyFormat::Matrix.new(
410
+ result.map(&:values),
411
+ header: result.first.keys,
412
+ type_map: type_map
413
+ )
414
+ matrix.rows
415
+ end
416
+ end
417
+ ```
418
+
419
+ Usage example with a fictional "users" database table (schema: `name`, `created_at`)
420
+ ```ruby
421
+ client = DbClient.new(host: '127.0.0.1', username: 'root', password: nil)
422
+ users = client.query(
423
+ 'SELECT * FROM users',
424
+ type_map: { created_at: :datetime! }
425
+ )
426
+ user = users.first
427
+ user.name # => buren
428
+ user.created_at.class # => Time
429
+ ```
430
+
379
431
  ## CLI
380
432
 
381
433
  > Perfect when you want to get something simple done quickly.
data/honey_format.gemspec CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency 'benchmark-ips'
26
26
  spec.add_development_dependency 'bundler', '> 1.10', '< 3'
27
27
  spec.add_development_dependency 'byebug'
28
- spec.add_development_dependency 'rake', '~> 10.0'
28
+ spec.add_development_dependency 'rake', '~> 12.3'
29
29
  spec.add_development_dependency 'rspec'
30
30
  spec.add_development_dependency 'simplecov'
31
31
  end
@@ -97,34 +97,7 @@ module HoneyFormat
97
97
  # Default converter registry
98
98
  # @return [Hash] hash with default converters
99
99
  def default_converters
100
- @default_converters ||= {
101
- # strict variants
102
- decimal!: StrictConvertDecimal,
103
- integer!: StrictConvertInteger,
104
- date!: StrictConvertDate,
105
- datetime!: StrictConvertDatetime,
106
- symbol!: StrictConvertSymbol,
107
- downcase!: StrictConvertDowncase,
108
- upcase!: StrictConvertUpcase,
109
- boolean!: StrictConvertBoolean,
110
- # safe variants
111
- decimal: ConvertDecimal,
112
- decimal_or_zero: ConvertDecimalOrZero,
113
- integer: ConvertInteger,
114
- integer_or_zero: ConvertIntegerOrZero,
115
- date: ConvertDate,
116
- datetime: ConvertDatetime,
117
- symbol: ConvertSymbol,
118
- downcase: ConvertDowncase,
119
- upcase: ConvertUpcase,
120
- boolean: ConvertBoolean,
121
- md5: ConvertMD5,
122
- hex: ConvertHex,
123
- nil: ConvertNil,
124
- blank: ConvertBlank,
125
- header_column: ConvertHeaderColumn,
126
- method_name: ConvertHeaderColumn,
127
- }.freeze
100
+ @default_converters ||= Converters::DEFAULT
128
101
  end
129
102
  end
130
103
  end
@@ -4,9 +4,9 @@ require 'set'
4
4
 
5
5
  module HoneyFormat
6
6
  # String values considered truthy
7
- TRUTHY = Set.new(%w[t T 1 y Y true TRUE]).freeze
7
+ TRUTHY = Set.new(%w[t T 1 y Y true TRUE] + [true]).freeze
8
8
  # String values considered falsy
9
- FALSY = Set.new(%w[f F 0 n N false FALSE]).freeze
9
+ FALSY = Set.new(%w[f F 0 n N false FALSE] + [false]).freeze
10
10
 
11
11
  # Tries to convert value boolean to, returns nil if it can't convert
12
12
  ConvertBoolean = proc do |v|
@@ -23,8 +23,8 @@ module HoneyFormat
23
23
  end
24
24
 
25
25
  # Convert to date or raise error
26
- StrictConvertDate = proc { |v| Date.parse(v) }
26
+ StrictConvertDate = proc { |v| v.is_a?(Date) ? v : Date.parse(v) }
27
27
 
28
28
  # Convert to datetime or raise error
29
- StrictConvertDatetime = proc { |v| Time.parse(v) }
29
+ StrictConvertDatetime = proc { |v| v.is_a?(Time) ? v : Time.parse(v) }
30
30
  end
@@ -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
@@ -9,4 +9,37 @@ require 'honey_format/converters/convert_string'
9
9
  module HoneyFormat
10
10
  # Convert to nil
11
11
  ConvertNil = proc {}
12
+
13
+ module Converters
14
+ DEFAULT = {
15
+ # strict variants
16
+ decimal!: StrictConvertDecimal,
17
+ integer!: StrictConvertInteger,
18
+ date!: StrictConvertDate,
19
+ datetime!: StrictConvertDatetime,
20
+ symbol!: StrictConvertSymbol,
21
+ downcase!: StrictConvertDowncase,
22
+ upcase!: StrictConvertUpcase,
23
+ strip!: StrictConvertStrip,
24
+ boolean!: StrictConvertBoolean,
25
+ # safe variants
26
+ decimal: ConvertDecimal,
27
+ decimal_or_zero: ConvertDecimalOrZero,
28
+ integer: ConvertInteger,
29
+ integer_or_zero: ConvertIntegerOrZero,
30
+ date: ConvertDate,
31
+ datetime: ConvertDatetime,
32
+ symbol: ConvertSymbol,
33
+ downcase: ConvertDowncase,
34
+ upcase: ConvertUpcase,
35
+ strip: ConvertStrip,
36
+ boolean: ConvertBoolean,
37
+ md5: ConvertMD5,
38
+ hex: ConvertHex,
39
+ nil: ConvertNil,
40
+ blank: ConvertBlank,
41
+ header_column: ConvertHeaderColumn,
42
+ method_name: ConvertHeaderColumn,
43
+ }.freeze
44
+ end
12
45
  end
@@ -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
@@ -16,10 +16,17 @@ module HoneyFormat
16
16
  # @raise [EmptyRowColumnsError] raised when there are no columns.
17
17
  # @raise [InvalidRowLengthError] raised when row has more columns than header columns.
18
18
  def initialize(rows, columns, builder: nil, type_map: {})
19
- builder = RowBuilder.new(columns, builder: builder, type_map: type_map)
19
+ @columns = columns
20
+ builder = RowBuilder.new(@columns, builder: builder, type_map: type_map)
20
21
  @rows = prepare_rows(builder, rows)
21
22
  end
22
23
 
24
+ # Row columns
25
+ # @return [Array<Symbol>] of column identifiers.
26
+ def columns
27
+ @columns
28
+ end
29
+
23
30
  # Returns true if rows contains no elements.
24
31
  # @return [true, false] true if rows contains no elements.
25
32
  def empty?
@@ -40,6 +47,12 @@ module HoneyFormat
40
47
  @rows
41
48
  end
42
49
 
50
+ # Return element at given position.
51
+ # @return [Row] of rows.
52
+ def [](index)
53
+ @rows[index]
54
+ end
55
+
43
56
  # Return the number of rows
44
57
  # @return [Integer] the number of rows
45
58
  def length
@@ -4,7 +4,7 @@ module HoneyFormat
4
4
  # Gem version
5
5
  VERSION = [
6
6
  MAJOR_VERSION = 0,
7
- MINOR_VERSION = 20,
7
+ MINOR_VERSION = 24,
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.20.0
4
+ version: 0.24.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: 2019-12-16 00:00:00.000000000 Z
11
+ date: 2021-07-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark-ips
@@ -64,14 +64,14 @@ dependencies:
64
64
  requirements:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: '10.0'
67
+ version: '12.3'
68
68
  type: :development
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: '10.0'
74
+ version: '12.3'
75
75
  - !ruby/object:Gem::Dependency
76
76
  name: rspec
77
77
  requirement: !ruby/object:Gem::Requirement
@@ -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.