From c007842eb05dc918b7be777f6bdd81da040cdf66 Mon Sep 17 00:00:00 2001 From: Steven Daniels Date: Mon, 23 Mar 2015 08:38:22 +0800 Subject: [PATCH] Fix :parse method with :clean option - Fixes Roo::Excelx.parse method when using :clean option - Fixes Roo::CSV.parse method when using :clean option - Added tests for parse with :clean option fixed space --- lib/roo/csv.rb | 10 ++++++++++ lib/roo/excelx.rb | 8 ++++++++ spec/lib/roo/csv_spec.rb | 14 ++++++++++++++ spec/lib/roo/excelx_spec.rb | 14 ++++++++++++++ test/files/parse_with_clean_option.csv | 1 + test/files/parse_with_clean_option.xlsx | Bin 0 -> 27929 bytes 6 files changed, 47 insertions(+) create mode 100644 test/files/parse_with_clean_option.csv create mode 100644 test/files/parse_with_clean_option.xlsx diff --git a/lib/roo/csv.rb b/lib/roo/csv.rb index cc44cc59..04a638ca 100644 --- a/lib/roo/csv.rb +++ b/lib/roo/csv.rb @@ -107,4 +107,14 @@ def read_cells(sheet = default_sheet) @last_column[sheet] -= 1 end end + + def clean_sheet(sheet) + read_cells(sheet) + + @cell.each_pair do |coord, value| + @cell[coord] = sanitize_value(value) if value.is_a?(::String) + end + + @cleaned[sheet] = true + end end diff --git a/lib/roo/excelx.rb b/lib/roo/excelx.rb index 82325e94..51630f18 100644 --- a/lib/roo/excelx.rb +++ b/lib/roo/excelx.rb @@ -487,6 +487,14 @@ def each_row_streaming(options={}) private + def clean_sheet(sheet) + @sheets_by_name[sheet].cells.each_pair do |coord, value| + @sheets_by_name[sheet].cells[coord] = sanitize_value(value) if value.is_a?(::String) + end + + @cleaned[sheet] = true + end + # Extracts all needed files from the zip file def process_zipfile(tmpdir, zipfilename) @sheet_files = [] diff --git a/spec/lib/roo/csv_spec.rb b/spec/lib/roo/csv_spec.rb index c9d3ad58..4d9f6c49 100644 --- a/spec/lib/roo/csv_spec.rb +++ b/spec/lib/roo/csv_spec.rb @@ -23,6 +23,20 @@ end end + describe '#parse_with_clean_option' do + subject do + csv.parse(options) + end + context 'with clean: true' do + let(:options) { {clean: true} } + let(:path) { 'test/files/parse_with_clean_option.csv' } + + it "doesn't blow up" do + expect { subject }.to_not raise_error + end + end + end + describe '#csv_options' do context 'when created with the csv_options option' do let(:options) do diff --git a/spec/lib/roo/excelx_spec.rb b/spec/lib/roo/excelx_spec.rb index 800d181f..8523c348 100644 --- a/spec/lib/roo/excelx_spec.rb +++ b/spec/lib/roo/excelx_spec.rb @@ -71,6 +71,20 @@ end end + describe '#parse_with_clean_option' do + let(:path) { 'test/files/parse_with_clean_option.xlsx' } + let(:options) { {clean: true} } + + context 'with clean: true' do + + it 'does not raise' do + expect do + xlsx.parse(options) + end.not_to raise_error + end + end + end + describe '#sheets' do let(:path) { 'test/files/numbers1.xlsx' } diff --git a/test/files/parse_with_clean_option.csv b/test/files/parse_with_clean_option.csv new file mode 100644 index 00000000..80058f7a --- /dev/null +++ b/test/files/parse_with_clean_option.csv @@ -0,0 +1 @@ +name Robert Eshleman \ No newline at end of file diff --git a/test/files/parse_with_clean_option.xlsx b/test/files/parse_with_clean_option.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..8ccd5afbf2caab69b44128925f0c3ac493267800 GIT binary patch literal 27929 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