Skip to content

Commit 024332d

Browse files
committed
fix for issue #299 : empty hash
1 parent 072067d commit 024332d

5 files changed

Lines changed: 85 additions & 12 deletions

File tree

.rubocop.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ Style/ClassMethods:
5858
Style/ConditionalAssignment:
5959
Enabled: false
6060

61+
Style/CommentAnnotation:
62+
Enabled: false
63+
6164
Style/CommentedKeyword:
6265
Enabled: false
6366

@@ -76,6 +79,9 @@ Style/Encoding:
7679
Style/EvalWithLocation:
7780
Enabled: false
7881

82+
Style/EvenOdd:
83+
Enabled: false
84+
7985
Style/FormatString:
8086
Enabled: false
8187

@@ -94,6 +100,9 @@ Style/IfUnlessModifier:
94100
Style/InverseMethods:
95101
Enabled: false
96102

103+
Style/Lambda:
104+
Enabled: false
105+
97106
Style/NestedTernaryOperator:
98107
Enabled: false
99108

@@ -115,6 +124,9 @@ Style/SafeNavigation:
115124
Style/SlicingWithRange:
116125
Enabled: false
117126

127+
Style/SoleNestedConditional:
128+
Enabled: false
129+
118130
Style/SpecialGlobalVars: # DANGER: unsafe rule!!
119131
Enabled: false
120132

@@ -135,8 +147,13 @@ Style/SymbolArray:
135147
Style/SymbolProc: # old Ruby versions can't do this
136148
Enabled: false
137149

150+
Style/TrailingCommaInArrayLiteral:
151+
Enabled: false
152+
EnforcedStyleForMultiline: consistent_comma
153+
138154
Style/TrailingCommaInHashLiteral:
139155
Enabled: false
156+
EnforcedStyleForMultiline: consistent_comma
140157

141158
Style/TrailingUnderscoreVariable:
142159
Enabled: false

lib/smarter_csv/parser.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ def cleanup_quotes(field, quote)
110110
end
111111

112112
# Replace double quotes with a single quote
113-
field.gsub!("#{quote * 2}", quote)
113+
field.gsub!((quote * 2).to_s, quote)
114114

115115
field
116116
end

lib/smarter_csv/writer.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def finalize
9090
mapped_headers = mapped_headers.map { |x| escape_csv_field(x) } if @force_quotes
9191

9292
@temp_file.rewind
93-
@output_file.write(mapped_headers.join(@col_sep) + @row_sep)
93+
@output_file.write(mapped_headers.join(@col_sep) + @row_sep) unless mapped_headers.empty?
9494
@output_file.write(@temp_file.read)
9595
@output_file.flush
9696
@output_file.close
@@ -120,7 +120,7 @@ def process_hash(hash)
120120
escape_csv_field(value) # for backwards compatibility
121121
end
122122

123-
@temp_file.write ordered_row.join(@col_sep) + @row_sep
123+
@temp_file.write(ordered_row.join(@col_sep) + @row_sep) unless ordered_row.empty?
124124
end
125125

126126
def map_value(key, value)

spec/features/special_cases/malformed_spec.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,5 @@
4545
end
4646
end
4747
end
48-
4948
end
5049
end

spec/smarter_csv/writer_spec.rb

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# frozen_string_literal: true
22

3-
# rubocop:disable Style/WordArray
43
RSpec.describe SmarterCSV::Writer do
54
subject(:create_csv_file) do
65
writer = SmarterCSV::Writer.new(file_path, options)
@@ -27,6 +26,61 @@
2726
]
2827
end
2928

29+
context 'when empty data is handed in' do
30+
let(:options) { {} }
31+
32+
subject(:write_csv) do
33+
SmarterCSV.generate(file_path, options) do |csv_writer|
34+
csv_writer << data
35+
end
36+
end
37+
38+
context 'when nil is passed in' do
39+
let(:data) { nil }
40+
it 'does not generate output' do
41+
write_csv
42+
output = File.read(file_path)
43+
expect(output).to eq ''
44+
end
45+
end
46+
47+
context 'when {} is passed in' do
48+
let(:data) { {} }
49+
it 'does not generate output' do
50+
write_csv
51+
output = File.read(file_path)
52+
expect(output).to eq ''
53+
end
54+
end
55+
56+
context 'when [] is passed in' do
57+
let(:data) { [] }
58+
it 'does not generate output' do
59+
write_csv
60+
output = File.read(file_path)
61+
expect(output).to eq ''
62+
end
63+
end
64+
65+
context 'when [{},nil] is passed in' do
66+
let(:data) { [{}, nil] }
67+
it 'does not generate output' do
68+
write_csv
69+
output = File.read(file_path)
70+
expect(output).to eq ''
71+
end
72+
end
73+
74+
context 'when [nil, {}, [], [{},nil]] is passed in' do
75+
let(:data) { [nil, {}, [], [{}, nil]] }
76+
it 'does not generate output' do
77+
write_csv
78+
output = File.read(file_path)
79+
expect(output).to eq ''
80+
end
81+
end
82+
end
83+
3084
context 'simplest case: one hash given' do
3185
let(:options) { {} }
3286
let(:data) do
@@ -236,16 +290,21 @@
236290
end
237291
end
238292

239-
context 'when we explicitly disable header discovery' do
293+
# NOTE:
294+
# * setting `discover_headers: false` is implicit when setting :headers or :map_headers
295+
# * that's why it does not make sense to set it manually to `false`.
296+
# * if you want to turn off header discovery, just provide one of those two options
297+
#
298+
context 'when we explicitly disable header discovery, but do not provide headers' do
240299
let(:options) do
241-
{ discover_headers: false } # THIS SHOULD NOT BE USED LIKE THIS!!
300+
{ discover_headers: false } # THIS DOES NOT MAKE SENSE without providing :headers or :map_headers
242301
end
243302

244303
it 'limits the CSV file to only the given headers' do
245304
create_csv_file
246305

247306
output = File.read(file_path)
248-
expect(output).to eq "\n\n\n\n\n" # THIS SHOULD NOT BE USED LIKE THIS!!
307+
expect(output).to eq '' # because it turns off header discovery and no headers provided
249308
end
250309
end
251310
end
@@ -268,7 +327,6 @@
268327
end
269328
end
270329

271-
272330
describe 'when special_char row_sep' do
273331
let(:options) { {} }
274332
let(:data_batches) do
@@ -339,14 +397,14 @@
339397
v.to_s
340398
end
341399
end,
342-
_all: ->(k, v) { v.is_a?(String) ? "\"#{v}\"" : v } # only double-quote string fields
400+
_all: ->(_k, v) { v.is_a?(String) ? "\"#{v}\"" : v } # only double-quote string fields
343401
}
344402
}
345403
end
346404
it 'applies all mappings in the correct order' do
347405
writer = SmarterCSV::Writer.new(file_path, options)
348406
writer << { name: 'Alice', age: 42, active: true, balance: 234.235 }
349-
writer << { name: 'Joe', age: 53, active: false, balance: 32100 }
407+
writer << { name: 'Joe', age: 53, active: false, balance: 32_100 }
350408
writer.finalize
351409

352410
output = File.read(file_path)
@@ -389,4 +447,3 @@
389447
end
390448
end
391449
end
392-
# rubocop:enable Style/WordArray

0 commit comments

Comments
 (0)