smarter_csv 1.14.0 → 1.14.1

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: 7f7308ee39fc18fb93f23273b32559ae83139375bfc84c975a1b6cf048368a5e
4
- data.tar.gz: a50d9ea0b40bf28adc829613d8d0b2744018b708453b96cc339653688a1c1f40
3
+ metadata.gz: c4619533008fc05b02a009b1409d1368d56245584baf52134511b45ff505f011
4
+ data.tar.gz: 051fa13106a0dfe41486accfee972a07c7d80670a65dd1066f07dfc600489be3
5
5
  SHA512:
6
- metadata.gz: baf9bad5261b6ab75d4d49fc7b0044536a9977955ef01d38b9d9431478649be8481a378a4b988b6091b7f2c5ba5f6c2a8899dfc2143f2bd11c834386453024d1
7
- data.tar.gz: 7283acb30cbdde33c463f369a619cc93235ea2931153babdcaedabe468cf50e198ab0264e9c70ee166a81cc072b44ab874d89e4de835379495155784b7a31035
6
+ metadata.gz: 5ee274a0a485e87f356940eeaf5e68d6af3d83dd72cd5199eca9729f6c760d0528ac2db8931c2d741521edb69251a4ff3d0c4d458f449a824f2b8110e7ad3a51
7
+ data.tar.gz: 87ac821280845041514a0418b94389296e6b03faf5c5fded8e2b0a0840015c03c477ad57d6a8268316b110adffb295882c81b7876c6f9f76a444531faed3c431
data/.rubocop.yml CHANGED
@@ -58,6 +58,9 @@ Style/ClassMethods:
58
58
  Style/ConditionalAssignment:
59
59
  Enabled: false
60
60
 
61
+ Style/CommentAnnotation:
62
+ Enabled: false
63
+
61
64
  Style/CommentedKeyword:
62
65
  Enabled: false
63
66
 
@@ -76,6 +79,9 @@ Style/Encoding:
76
79
  Style/EvalWithLocation:
77
80
  Enabled: false
78
81
 
82
+ Style/EvenOdd:
83
+ Enabled: false
84
+
79
85
  Style/FormatString:
80
86
  Enabled: false
81
87
 
@@ -94,9 +100,15 @@ Style/IfUnlessModifier:
94
100
  Style/InverseMethods:
95
101
  Enabled: false
96
102
 
103
+ Style/Lambda:
104
+ Enabled: false
105
+
97
106
  Style/NestedTernaryOperator:
98
107
  Enabled: false
99
108
 
109
+ Style/OptionalBooleanParameter:
110
+ Enabled: false
111
+
100
112
  Style/PreferredHashMethods:
101
113
  Enabled: false
102
114
 
@@ -115,6 +127,9 @@ Style/SafeNavigation:
115
127
  Style/SlicingWithRange:
116
128
  Enabled: false
117
129
 
130
+ Style/SoleNestedConditional:
131
+ Enabled: false
132
+
118
133
  Style/SpecialGlobalVars: # DANGER: unsafe rule!!
119
134
  Enabled: false
120
135
 
@@ -135,8 +150,13 @@ Style/SymbolArray:
135
150
  Style/SymbolProc: # old Ruby versions can't do this
136
151
  Enabled: false
137
152
 
153
+ Style/TrailingCommaInArrayLiteral:
154
+ Enabled: false
155
+ EnforcedStyleForMultiline: consistent_comma
156
+
138
157
  Style/TrailingCommaInHashLiteral:
139
158
  Enabled: false
159
+ EnforcedStyleForMultiline: consistent_comma
140
160
 
141
161
  Style/TrailingUnderscoreVariable:
142
162
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,6 +1,11 @@
1
1
 
2
2
  # SmarterCSV 1.x Change Log
3
3
 
4
+ ## 1.14.1 (2025-04-09)
5
+ * bugfix: empty hash results in a blank line ([issue 299](https://github.com/tilo/smarter_csv/issues/299))
6
+ * bugfix: automatically quote problematic headers ([issue #300](https://github.com/tilo/smarter_csv/issues/300))
7
+ * new option: `quote_headers` allows to explicitly quote all headers
8
+
4
9
  ## 1.14.0 (2025-04-07)
5
10
  * adding advanced configuration options for writing CSV files. ([issue 297](https://github.com/tilo/smarter_csv/issues/297) thanks to Robert Reiz, [issue 296](https://github.com/tilo/smarter_csv/issues/296))
6
11
 
data/README.md CHANGED
@@ -49,7 +49,8 @@ Or install it yourself as:
49
49
  * [Parsing CSV Files in Ruby with SmarterCSV](https://tilo-sloboda.medium.com/parsing-csv-files-in-ruby-with-smartercsv-6ce66fb6cf38)
50
50
  * [Processing 1.4 Million CSV Records in Ruby, fast ](https://lcx.wien/blog/processing-14-million-csv-records-in-ruby/)
51
51
  * [Faster Parsing CSV with Parallel Processing](http://xjlin0.github.io/tech/2015/05/25/faster-parsing-csv-with-parallel-processing) by [Jack lin](https://github.com/xjlin0/)
52
- * [The original post](http://www.unixgods.org/Ruby/process_csv_as_hashes.html) that started SmarterCSV
52
+ * The original [Stackoverflow Question](https://stackoverflow.com/questions/7788618/update-mongodb-with-array-from-csv-join-table/7788746#7788746) that inspired SmarterCSV
53
+ * [The original post](http://www.unixgods.org/Ruby/process_csv_as_hashes.html) for SmarterCSV
53
54
 
54
55
  # [ChangeLog](./CHANGELOG.md)
55
56
 
@@ -62,14 +62,14 @@ The simplified interface takes a block:
62
62
  ### Full Interface
63
63
 
64
64
  ```
65
- writer = SmarterCSV::Writer.new(file_path, options)
65
+ csv_writer = SmarterCSV::Writer.new(file_path, options)
66
66
 
67
67
  MyModel.find_in_batches(batch_size: 100) do |batch|
68
68
  batch.pluck(:name, :description, :instructor).each do |record|
69
69
  csv_writer << record
70
70
  end
71
71
 
72
- writer.finalize
72
+ csv_writer.finalize
73
73
  ```
74
74
 
75
75
  ## Advanced Features: Customizing the Output Format
@@ -141,7 +141,7 @@ You can also use the special keyword `:_all` to define transformations that are
141
141
  value_converters: {
142
142
  disable_auto_quoting: true, # ⚠️ Important: turn off auto-quoting because we're messing with it below
143
143
  active: ->(v) { !!v ? 'YES' : 'NO' },
144
- _all: ->(k, v) { v.is_a?(String) ? "\"#{v}\"" : v } # only double-quote string fields
144
+ _all: ->(_k, v) { v.is_a?(String) ? "\"#{v}\"" : v } # only double-quote string fields
145
145
  }
146
146
  }
147
147
  ```
@@ -110,7 +110,7 @@ module SmarterCSV
110
110
  end
111
111
 
112
112
  # Replace double quotes with a single quote
113
- field.gsub!("#{quote * 2}", quote)
113
+ field.gsub!((quote * 2).to_s, quote)
114
114
 
115
115
  field
116
116
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SmarterCSV
4
- VERSION = "1.14.0"
4
+ VERSION = "1.14.1"
5
5
  end
@@ -29,6 +29,7 @@ module SmarterCSV
29
29
  # quote_char : defaults to "
30
30
  # discover_headers : defaults to true
31
31
  # headers : defaults to []
32
+ # quote_headers: defaults to false
32
33
  # force_quotes: defaults to false
33
34
  # map_headers: defaults to {}, can be a hash of key -> value mappings
34
35
  # value_converters: optional hash of key -> lambda to control serialization
@@ -48,6 +49,7 @@ module SmarterCSV
48
49
  @col_sep = options[:col_sep] || ','
49
50
  @quote_char = options[:quote_char] || '"'
50
51
  @force_quotes = options[:force_quotes] == true
52
+ @quote_headers = options[:quote_headers] == true
51
53
  @disable_auto_quoting = options[:disable_auto_quoting] == true
52
54
  @value_converters = options[:value_converters] || {}
53
55
  @map_all_keys = @value_converters.has_key?(:_all)
@@ -55,7 +57,7 @@ module SmarterCSV
55
57
 
56
58
  @discover_headers = true
57
59
  if options.has_key?(:discover_headers)
58
- @discover_headers = options[:discover_headers] == true # ⚠️ this option should not be exposed
60
+ @discover_headers = options[:discover_headers] == true
59
61
  else
60
62
  @discover_headers = !(options.has_key?(:map_headers) || options.has_key?(:headers))
61
63
  end
@@ -87,10 +89,11 @@ module SmarterCSV
87
89
 
88
90
  def finalize
89
91
  mapped_headers = @headers.map { |header| @map_headers[header] || header }
90
- mapped_headers = mapped_headers.map { |x| escape_csv_field(x) } if @force_quotes
92
+ force_quotes = @quote_headers || @force_quotes
93
+ mapped_headers = mapped_headers.map { |x| escape_csv_field(x, force_quotes) }
91
94
 
92
95
  @temp_file.rewind
93
- @output_file.write(mapped_headers.join(@col_sep) + @row_sep)
96
+ @output_file.write(mapped_headers.join(@col_sep) + @row_sep) unless mapped_headers.empty?
94
97
  @output_file.write(@temp_file.read)
95
98
  @output_file.flush
96
99
  @output_file.close
@@ -117,10 +120,10 @@ module SmarterCSV
117
120
  # then apply general mapping rules
118
121
  value = map_all_values(header, value) if @map_all_keys
119
122
 
120
- escape_csv_field(value) # for backwards compatibility
123
+ escape_csv_field(value, @force_quotes) # for backwards compatibility
121
124
  end
122
125
 
123
- @temp_file.write ordered_row.join(@col_sep) + @row_sep
126
+ @temp_file.write(ordered_row.join(@col_sep) + @row_sep) unless ordered_row.empty?
124
127
  end
125
128
 
126
129
  def map_value(key, value)
@@ -131,13 +134,13 @@ module SmarterCSV
131
134
  @value_converters[:_all].call(key, value)
132
135
  end
133
136
 
134
- def escape_csv_field(field)
137
+ def escape_csv_field(field, force_quotes = false)
135
138
  str = field.to_s
136
139
  return str if @disable_auto_quoting
137
140
 
138
141
  # double-quote fields if we force that, or if the field contains the comma, new-line, or quote character
139
142
  contains_special_char = str.to_s.match(@quote_regex)
140
- if @force_quotes || contains_special_char
143
+ if force_quotes || contains_special_char
141
144
  str = str.gsub(@quote_char, @quote_char * 2) if contains_special_char # escape double-quote
142
145
 
143
146
  "\"#{str}\""
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smarter_csv
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.14.0
4
+ version: 1.14.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tilo Sloboda
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-04-07 00:00:00.000000000 Z
11
+ date: 2025-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: awesome_print