From 95644c74e8ec3d99d8273454b252b1cb79309e7e Mon Sep 17 00:00:00 2001 From: Luke Cowell Date: Tue, 9 Oct 2012 15:05:43 -0700 Subject: [PATCH] add capability to process a file and return a count of imported rows This is useful when importing large data files as #import builds an array with all results and returns that. --- lib/csv-mapper.rb | 47 +++++++++++++++++++++++++++++------------ spec/csv-mapper_spec.rb | 7 ++++++ 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/lib/csv-mapper.rb b/lib/csv-mapper.rb index eaf4bb0..85af926 100644 --- a/lib/csv-mapper.rb +++ b/lib/csv-mapper.rb @@ -95,28 +95,49 @@ def map_csv(&map_block) # :map:: Specify an instance of a RowMap to take presidence over a given block defintion. # def import(data, options={}, &map_block) - csv_data = options[:type] == :io ? data : File.new(data, 'r') - - config = { :type => :file_path, - :map => map_csv_with_data(csv_data, &map_block) }.merge!(options) - - map = config[:map] - results = [] - FasterCSV.new(csv_data, map.parser_options ).each_with_index do |row, i| - results << map.parse(row) if i >= map.start_at_row && i <= map.stop_at_row + build_results(data, map_block, options) do |result| + results << result end - results - end + end + + # Process works the same was as import except that it returns a count of + # imported rows instead of the results. This is useful for processing large + # files. + def process(data, options={}, &map_block) + count = 0 + build_results(data, map_block, options) do |result| + count = count.succ + end + + count + end protected # Create a new RowMap instance from the definition in the given block and pass the csv_data. def map_csv_with_data(csv_data, &map_block) # :nodoc: CsvMapper::RowMap.new(self, csv_data, &map_block) end - + + private + # Process each row and yield result to caller + def build_results(data, map_block, options={}) + csv_data = options[:type] == :io ? data : File.new(data, 'r') + + config = { :type => :file_path, + :map => map_csv_with_data(csv_data, &map_block) }.merge!(options) + + map = config[:map] + + FasterCSV.new(csv_data, map.parser_options ).each_with_index do |row, i| + if i >= map.start_at_row && i <= map.stop_at_row + yield map.parse(row) + end + end + end + extend self end -require 'csv-mapper/row_map' \ No newline at end of file +require 'csv-mapper/row_map' diff --git a/spec/csv-mapper_spec.rb b/spec/csv-mapper_spec.rb index e12628c..97689ca 100644 --- a/spec/csv-mapper_spec.rb +++ b/spec/csv-mapper_spec.rb @@ -89,6 +89,13 @@ def upcase_name(row) results[0].first_name.should == 'JOHN' end + + it "should allow us to not capture the output and return a row count instead" do + io = "foo,bar,00,01\na,b,c,d" + results = @mapped.process(io, :type => :io, :capture_output => false) + + results.should == 2 + end end describe "extended" do