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 +4 -4
- data/.rubocop.yml +20 -0
- data/CHANGELOG.md +5 -0
- data/README.md +2 -1
- data/docs/basic_write_api.md +3 -3
- data/lib/smarter_csv/parser.rb +1 -1
- data/lib/smarter_csv/version.rb +1 -1
- data/lib/smarter_csv/writer.rb +10 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4619533008fc05b02a009b1409d1368d56245584baf52134511b45ff505f011
|
4
|
+
data.tar.gz: 051fa13106a0dfe41486accfee972a07c7d80670a65dd1066f07dfc600489be3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
*
|
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
|
|
data/docs/basic_write_api.md
CHANGED
@@ -62,14 +62,14 @@ The simplified interface takes a block:
|
|
62
62
|
### Full Interface
|
63
63
|
|
64
64
|
```
|
65
|
-
|
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
|
-
|
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: ->(
|
144
|
+
_all: ->(_k, v) { v.is_a?(String) ? "\"#{v}\"" : v } # only double-quote string fields
|
145
145
|
}
|
146
146
|
}
|
147
147
|
```
|
data/lib/smarter_csv/parser.rb
CHANGED
data/lib/smarter_csv/version.rb
CHANGED
data/lib/smarter_csv/writer.rb
CHANGED
@@ -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
|
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
|
-
|
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
|
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
|
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.
|
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-
|
11
|
+
date: 2025-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: awesome_print
|