From 8465f6bf8a6afd1b2f1a10ca8dd99ea82b7cb344 Mon Sep 17 00:00:00 2001 From: masa21kik Date: Sat, 31 May 2014 22:29:21 +0900 Subject: [PATCH 1/5] change interface --- lib/csvconv.rb | 14 +++++++------- lib/csvconv/converter.rb | 4 ++-- lib/csvconv/formatter.rb | 8 ++++---- spec/csvconv_spec.rb | 14 ++++++-------- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/lib/csvconv.rb b/lib/csvconv.rb index 0a40ab3..0817aac 100644 --- a/lib/csvconv.rb +++ b/lib/csvconv.rb @@ -5,20 +5,20 @@ # CSV Converter module CSVConv - def to_json(input, output, options) + def csv2json(input, options) cv = Converter.new(:json, options) - cv.convert_stream(input, output) + cv.convert(input) end - def to_yaml(input, output, options) + def csv2yaml(input, options) cv = Converter.new(:yaml, options) - cv.convert(input, output) + cv.convert(input) end - def to_ltsv(input, output, options) + def csv2ltsv(input, options) cv = Converter.new(:ltsv, options) - cv.convert_stream(input, output) + cv.convert(input) end - module_function :to_json, :to_yaml, :to_ltsv + module_function :csv2json, :csv2yaml, :csv2ltsv end diff --git a/lib/csvconv/converter.rb b/lib/csvconv/converter.rb index d371371..3f76424 100644 --- a/lib/csvconv/converter.rb +++ b/lib/csvconv/converter.rb @@ -7,13 +7,13 @@ def initialize(format, options) @header = options[:header] end - def convert(input, output) + def convert(input) @header ||= Parser.read_header(input, @sep) hash_array = [] while (line = input.gets) hash_array << Parser.parse_line(line, @header, @sep) end - output.puts Formatter.send(@format, hash_array) + Formatter.send(@format, hash_array) end def convert_stream(input, output) diff --git a/lib/csvconv/formatter.rb b/lib/csvconv/formatter.rb index 91c9ea6..d566cd8 100644 --- a/lib/csvconv/formatter.rb +++ b/lib/csvconv/formatter.rb @@ -6,8 +6,8 @@ module CSVConv module Formatter def json(hash_array) hash_array.map do |hash| - hash.to_json - end + hash.to_json + "\n" + end.join end def yaml(hash_array) @@ -16,8 +16,8 @@ def yaml(hash_array) def ltsv(hash_array) hash_array.map do |hash| - hash.map { |key, val| [key, val].join(':') }.join("\t") - end + hash.map { |key, val| [key, val].join(':') }.join("\t") + "\n" + end.join end module_function :json, :yaml, :ltsv diff --git a/spec/csvconv_spec.rb b/spec/csvconv_spec.rb index 1f37e44..5b4f095 100644 --- a/spec/csvconv_spec.rb +++ b/spec/csvconv_spec.rb @@ -8,18 +8,16 @@ shared_examples_for 'convert file format' do before do @input = File.open(input_csv) - @output = StringIO.new end it 'convert file format' do - CSVConv.send("to_#{format}", @input, @output, options) - expected_result = File.read(input_csv.sub(/csv$/, format)) - expect(@output.string).to eq expected_result + actual = CSVConv.send("csv2#{format}", @input, options) + expected = File.read(input_csv.sub(/csv$/, format)) + expect(actual).to eq expected end after do @input.close - @output.close end end @@ -29,17 +27,17 @@ let(:input_csv) { File.join(fixture_dir, 'books.csv') } let(:options) { {} } - describe '#to_json' do + describe '#csv2json' do let(:format) { 'json' } it_behaves_like 'convert file format' end - describe '#to_yaml' do + describe '#csv2yaml' do let(:format) { 'yaml' } it_behaves_like 'convert file format' end - describe '#to_ltsv' do + describe '#csv2ltsv' do let(:format) { 'ltsv' } it_behaves_like 'convert file format' end From 81611418cb2a92358d0434f7343fb05340e5fd6b Mon Sep 17 00:00:00 2001 From: masa21kik Date: Sat, 31 May 2014 23:37:46 +0900 Subject: [PATCH 2/5] add test case of tsv input --- spec/csvconv_spec.rb | 26 +++++++++++++++++++++++--- spec/fixtures/books.tsv | 6 ++++++ 2 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 spec/fixtures/books.tsv diff --git a/spec/csvconv_spec.rb b/spec/csvconv_spec.rb index 5b4f095..1c272eb 100644 --- a/spec/csvconv_spec.rb +++ b/spec/csvconv_spec.rb @@ -7,12 +7,12 @@ shared_examples_for 'convert file format' do before do - @input = File.open(input_csv) + @input = File.open(input_path) end it 'convert file format' do actual = CSVConv.send("csv2#{format}", @input, options) - expected = File.read(input_csv.sub(/csv$/, format)) + expected = File.read(input_path.sub(/[^\.]+$/, format)) expect(actual).to eq expected end @@ -24,7 +24,7 @@ let(:fixture_dir) { File.expand_path('../fixtures', __FILE__) } context 'CSV with header (books.csv)' do - let(:input_csv) { File.join(fixture_dir, 'books.csv') } + let(:input_path) { File.join(fixture_dir, 'books.csv') } let(:options) { {} } describe '#csv2json' do @@ -42,4 +42,24 @@ it_behaves_like 'convert file format' end end + + context 'TSV with header (books.tsv)' do + let(:input_path) { File.join(fixture_dir, 'books.tsv') } + let(:options) { { sep: "\t" } } + + describe '#csv2json' do + let(:format) { 'json' } + it_behaves_like 'convert file format' + end + + describe '#csv2yaml' do + let(:format) { 'yaml' } + it_behaves_like 'convert file format' + end + + describe '#csv2ltsv' do + let(:format) { 'ltsv' } + it_behaves_like 'convert file format' + end + end end diff --git a/spec/fixtures/books.tsv b/spec/fixtures/books.tsv new file mode 100644 index 0000000..b9e7fcc --- /dev/null +++ b/spec/fixtures/books.tsv @@ -0,0 +1,6 @@ +Title Author Price +The Fault in Our Stars John Green 12.99 +City of Heavenly Fire (The Mortal Instruments) Cassandra Clare 24.99 +Oh, The Places You'll Go! Dr. Seuss 17.99 +Capital in the Twenty-First Century Thomas Piketty 39.95 +Skin Game (Dresden Files) Jim Butcher 27.95 From 3a54f1d55b73de5b70a9a8caf5e44bacbbc54fc9 Mon Sep 17 00:00:00 2001 From: masa21kik Date: Sat, 31 May 2014 23:40:08 +0900 Subject: [PATCH 3/5] add test case of streaming process --- spec/csvconv/converter_spec.rb | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 spec/csvconv/converter_spec.rb diff --git a/spec/csvconv/converter_spec.rb b/spec/csvconv/converter_spec.rb new file mode 100644 index 0000000..f10c943 --- /dev/null +++ b/spec/csvconv/converter_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe CSVConv::Converter do + shared_examples_for 'convert file format stream' do + before do + @input = File.open(input_path) + @output = StringIO.new + end + + it 'convert file format stream' do + cv = CSVConv::Converter.new(format, options) + cv.convert_stream(@input, @output) + actual = @output.string + expected = File.read(input_path.sub(/[^\.]+$/, format)) + expect(actual).to eq expected + end + + after do + @input.close + @output.close + end + end + + let(:fixture_dir) { File.expand_path('../../fixtures', __FILE__) } + + context 'CSV with header (books.csv)' do + let(:input_path) { File.join(fixture_dir, 'books.csv') } + let(:options) { {} } + + context 'json' do + let(:format) { 'json' } + it_behaves_like 'convert file format stream' + end + + context 'ltsv' do + let(:format) { 'ltsv' } + it_behaves_like 'convert file format stream' + end + end +end From 6aa922e2733e82ed8a8163597c3653d9d64976ca Mon Sep 17 00:00:00 2001 From: masa21kik Date: Sat, 31 May 2014 23:47:37 +0900 Subject: [PATCH 4/5] add test case for no header csv input --- spec/csvconv_spec.rb | 28 +++++++++++++++++++++++++++- spec/fixtures/books_noheader.csv | 5 +++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 spec/fixtures/books_noheader.csv diff --git a/spec/csvconv_spec.rb b/spec/csvconv_spec.rb index 1c272eb..796c409 100644 --- a/spec/csvconv_spec.rb +++ b/spec/csvconv_spec.rb @@ -10,9 +10,15 @@ @input = File.open(input_path) end + def expect_file_path + dir = File.dirname(input_path) + base = File.basename(input_path, '.*').sub('_noheader', '') + File.join(dir, "#{base}.#{format}") + end + it 'convert file format' do actual = CSVConv.send("csv2#{format}", @input, options) - expected = File.read(input_path.sub(/[^\.]+$/, format)) + expected = File.read(expect_file_path) expect(actual).to eq expected end @@ -43,6 +49,26 @@ end end + context 'CSV without header (books.csv)' do + let(:input_path) { File.join(fixture_dir, 'books_noheader.csv') } + let(:options) { { header: %w(Title Author Price) } } + + describe '#csv2json' do + let(:format) { 'json' } + it_behaves_like 'convert file format' + end + + describe '#csv2yaml' do + let(:format) { 'yaml' } + it_behaves_like 'convert file format' + end + + describe '#csv2ltsv' do + let(:format) { 'ltsv' } + it_behaves_like 'convert file format' + end + end + context 'TSV with header (books.tsv)' do let(:input_path) { File.join(fixture_dir, 'books.tsv') } let(:options) { { sep: "\t" } } diff --git a/spec/fixtures/books_noheader.csv b/spec/fixtures/books_noheader.csv new file mode 100644 index 0000000..ddb6305 --- /dev/null +++ b/spec/fixtures/books_noheader.csv @@ -0,0 +1,5 @@ +The Fault in Our Stars,John Green,12.99 +City of Heavenly Fire (The Mortal Instruments),Cassandra Clare,24.99 +"Oh, The Places You'll Go!",Dr. Seuss,17.99 +Capital in the Twenty-First Century,Thomas Piketty,39.95 +Skin Game (Dresden Files),Jim Butcher,27.95 From 13857d2ba83fe7aa20be5f7cddc9b067d0d97e7d Mon Sep 17 00:00:00 2001 From: masa21kik Date: Sat, 31 May 2014 23:51:20 +0900 Subject: [PATCH 5/5] update command --- bin/csvconv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/csvconv b/bin/csvconv index 148e236..ce36533 100755 --- a/bin/csvconv +++ b/bin/csvconv @@ -41,7 +41,7 @@ if $PROGRAM_NAME == __FILE__ inputs = ARGV.empty? ? [STDIN] : ARGV.map { |f| File.open(f) } inputs.each do |input| - CSVConv.send("to_#{format.to_s}", input, output, options) + output.puts CSVConv.send("csv2#{format.to_s}", input, options) end output.close