smarter_csv 1.1.0 → 1.1.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/README.md +27 -1
 - data/lib/smarter_csv/smarter_csv.rb +35 -18
 - data/lib/smarter_csv/version.rb +1 -1
 - data/spec/fixtures/malformed.csv +3 -0
 - data/spec/fixtures/malformed_header.csv +3 -0
 - data/spec/fixtures/skip_lines.csv +8 -0
 - data/spec/smarter_csv/close_file_spec.rb +15 -0
 - data/spec/smarter_csv/malformed_spec.rb +21 -0
 - data/spec/smarter_csv/skip_lines_spec.rb +29 -0
 - metadata +14 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 34d6c592bebe9d6b1d8f87f9f59ecf4a7d3b3a9d
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: fe722f38c4962a312c4db7e14cb72e735426db82
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 75f5c56cfdeeef41be34f17bfbec30ae201c41463ad9aa6c7da7b5031c63fa1da27ef5120c245329eec108551fae722a5d156e09ead62c2e6aa34ce8edfe4cd8
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 2d3b83fa5e7f4eada8d7f03df50890441f594b8db6d34df4d2c07164c73beda7b9963d596ce43d2ad74ffddb83efb4bdea8ca83d780d7f3129c258c6d21bdb70
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -20,7 +20,7 @@ One `smarter_csv` user wrote: 
     | 
|
| 
       20 
20 
     | 
    
         
             
             * able to ignore "columns" in the input (delete columns)
         
     | 
| 
       21 
21 
     | 
    
         
             
             * able to eliminate nil or empty fields from the result hashes (default)
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
       23 
     | 
    
         
            -
            NOTE; This Gem is only for importing CSV files - writing of CSV files is not supported.
         
     | 
| 
      
 23 
     | 
    
         
            +
            NOTE; This Gem is only for importing CSV files - writing of CSV files is not supported at this time.
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
25 
     | 
    
         
             
            ### Why?
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
         @@ -130,6 +130,8 @@ and how the `process` method returns the number of chunks when called with a blo 
     | 
|
| 
       130 
130 
     | 
    
         | 
| 
       131 
131 
     | 
    
         
             
            #### Example 6: Using Value Converters
         
     | 
| 
       132 
132 
     | 
    
         | 
| 
      
 133 
     | 
    
         
            +
            NOTE: If you use `key_mappings` and `value_converters`, make sure that the value converters has references the keys based on the final mapped name, not the original name in the CSV file.
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
       133 
135 
     | 
    
         
             
                $ cat spec/fixtures/with_dates.csv
         
     | 
| 
       134 
136 
     | 
    
         
             
                first,last,date,price
         
     | 
| 
       135 
137 
     | 
    
         
             
                Ben,Miller,10/30/1998,$44.50
         
     | 
| 
         @@ -163,6 +165,9 @@ and how the `process` method returns the number of chunks when called with a blo 
     | 
|
| 
       163 
165 
     | 
    
         
             
                data[0][:price].class
         
     | 
| 
       164 
166 
     | 
    
         
             
                  => Float
         
     | 
| 
       165 
167 
     | 
    
         | 
| 
      
 168 
     | 
    
         
            +
            ## Parallel Processing
         
     | 
| 
      
 169 
     | 
    
         
            +
            [Jack](https://github.com/xjlin0) wrote an interesting article about [Speeding up CSV parsing with parallel processing](http://xjlin0.github.io/tech/2015/05/25/faster-parsing-csv-with-parallel-processing/)
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
       166 
171 
     | 
    
         
             
            ## Documentation
         
     | 
| 
       167 
172 
     | 
    
         | 
| 
       168 
173 
     | 
    
         
             
            The `process` method reads and processes a "generalized" CSV file and returns the contents either as an Array of Hashes,
         
     | 
| 
         @@ -198,6 +203,8 @@ The options and the block are optional. 
     | 
|
| 
       198 
203 
     | 
    
         
             
                 | :headers_in_file            |   true   | Whether or not the file contains headers as the first line.                          |
         
     | 
| 
       199 
204 
     | 
    
         
             
                 |                             |          | Important if the file does not contain headers,                                      |
         
     | 
| 
       200 
205 
     | 
    
         
             
                 |                             |          | otherwise you would lose the first line of data.                                     |
         
     | 
| 
      
 206 
     | 
    
         
            +
                 | :skip_lines                 |   nil    | how many lines to skip before the first line or header line is processed             |
         
     | 
| 
      
 207 
     | 
    
         
            +
                 | :force_utf8                 |   false  | force UTF-8 encoding of all lines (including headers) in the CSV file                |     
         
     | 
| 
       201 
208 
     | 
    
         
             
                 ---------------------------------------------------------------------------------------------------------------------------------
         
     | 
| 
       202 
209 
     | 
    
         
             
                 | :value_converters           |   nil    | supply a hash of :header => KlassName; the class needs to implement self.convert(val)|
         
     | 
| 
       203 
210 
     | 
    
         
             
                 | :remove_empty_values        |   true   | remove values which have nil or empty strings as values                              |
         
     | 
| 
         @@ -270,9 +277,22 @@ Or install it yourself as: 
     | 
|
| 
       270 
277 
     | 
    
         | 
| 
       271 
278 
     | 
    
         
             
                $ gem install smarter_csv
         
     | 
| 
       272 
279 
     | 
    
         | 
| 
      
 280 
     | 
    
         
            +
            ## Upcoming
         
     | 
| 
      
 281 
     | 
    
         
            +
             
     | 
| 
      
 282 
     | 
    
         
            +
            Planned in the next releases:
         
     | 
| 
      
 283 
     | 
    
         
            +
             * programmatic header transformations
         
     | 
| 
      
 284 
     | 
    
         
            +
             * CSV command line
         
     | 
| 
       273 
285 
     | 
    
         | 
| 
       274 
286 
     | 
    
         
             
            ## Changes
         
     | 
| 
       275 
287 
     | 
    
         | 
| 
      
 288 
     | 
    
         
            +
            #### 1.1.1 (2016-11-26)  
         
     | 
| 
      
 289 
     | 
    
         
            +
             * added option to `skip_lines` (thanks to wal)
         
     | 
| 
      
 290 
     | 
    
         
            +
             * added option to `force_utf8` encoding (thanks to jordangraft)
         
     | 
| 
      
 291 
     | 
    
         
            +
             * bugfix if no headers in input data (thanks to esBeee)
         
     | 
| 
      
 292 
     | 
    
         
            +
             * ensure input file is closed (thanks to waldyr)
         
     | 
| 
      
 293 
     | 
    
         
            +
             * improved verbose output (thankd to benmaher)
         
     | 
| 
      
 294 
     | 
    
         
            +
             * improved documentation
         
     | 
| 
      
 295 
     | 
    
         
            +
             
         
     | 
| 
       276 
296 
     | 
    
         
             
            #### 1.1.0 (2015-07-26)
         
     | 
| 
       277 
297 
     | 
    
         
             
             * added feature :value_converters, which allows parsing of dates, money, and other things (thanks to Raphaël Bleuse, Lucas Camargo de Almeida, Alejandro)
         
     | 
| 
       278 
298 
     | 
    
         
             
             * added error if :headers_in_file is set to false, and no :user_provided_headers are given (thanks to innhyu)
         
     | 
| 
         @@ -383,6 +403,7 @@ Please [open an Issue on GitHub](https://github.com/tilo/smarter_csv/issues) if 
     | 
|
| 
       383 
403 
     | 
    
         
             
            Many thanks to people who have filed issues and sent comments.
         
     | 
| 
       384 
404 
     | 
    
         
             
            And a special thanks to those who contributed pull requests:
         
     | 
| 
       385 
405 
     | 
    
         | 
| 
      
 406 
     | 
    
         
            +
             * [Jack 0](https://github.com/xjlin0)
         
     | 
| 
       386 
407 
     | 
    
         
             
             * [Alejandro](https://github.com/agaviria)
         
     | 
| 
       387 
408 
     | 
    
         
             
             * [Lucas Camargo de Almeida](https://github.com/lcalmeida)
         
     | 
| 
       388 
409 
     | 
    
         
             
             * [Raphaël Bleuse](https://github.com/bleuse)
         
     | 
| 
         @@ -402,6 +423,11 @@ And a special thanks to those who contributed pull requests: 
     | 
|
| 
       402 
423 
     | 
    
         
             
             * [Jordan Running](https://github.com/jrunning)
         
     | 
| 
       403 
424 
     | 
    
         
             
             * [Dave Sanders](https://github.com/DaveSanders)
         
     | 
| 
       404 
425 
     | 
    
         
             
             * [Hugo Lepetit](https://github.com/giglemad)
         
     | 
| 
      
 426 
     | 
    
         
            +
             * [esBeee](https://github.com/esBeee)
         
     | 
| 
      
 427 
     | 
    
         
            +
             * [Waldyr de Souza](https://github.com/waldyr)
         
     | 
| 
      
 428 
     | 
    
         
            +
             * [Ben Maher](https://github.com/benmaher)
         
     | 
| 
      
 429 
     | 
    
         
            +
             * [Wal McConnell](https://github.com/wal)
         
     | 
| 
      
 430 
     | 
    
         
            +
             * [Jordan Graft](https://github.com/jordangraft)
         
     | 
| 
       405 
431 
     | 
    
         | 
| 
       406 
432 
     | 
    
         | 
| 
       407 
433 
     | 
    
         
             
            ## Contributing
         
     | 
| 
         @@ -9,14 +9,15 @@ module SmarterCSV 
     | 
|
| 
       9 
9 
     | 
    
         
             
                  :remove_empty_values => true, :remove_zero_values => false , :remove_values_matching => nil , :remove_empty_hashes => true , :strip_whitespace => true,
         
     | 
| 
       10 
10 
     | 
    
         
             
                  :convert_values_to_numeric => true, :strip_chars_from_headers => nil , :user_provided_headers => nil , :headers_in_file => true,
         
     | 
| 
       11 
11 
     | 
    
         
             
                  :comment_regexp => /^#/, :chunk_size => nil , :key_mapping_hash => nil , :downcase_header => true, :strings_as_keys => false, :file_encoding => 'utf-8',
         
     | 
| 
       12 
     | 
    
         
            -
                  :remove_unmapped_keys => false, :keep_original_headers => false, :value_converters => nil,
         
     | 
| 
      
 12 
     | 
    
         
            +
                  :remove_unmapped_keys => false, :keep_original_headers => false, :value_converters => nil, :skip_lines => nil, :force_utf8 => false
         
     | 
| 
       13 
13 
     | 
    
         
             
                }
         
     | 
| 
       14 
14 
     | 
    
         
             
                options = default_options.merge(options)
         
     | 
| 
       15 
15 
     | 
    
         
             
                csv_options = options.select{|k,v| [:col_sep, :row_sep, :quote_char].include?(k)} # options.slice(:col_sep, :row_sep, :quote_char)
         
     | 
| 
       16 
16 
     | 
    
         
             
                headerA = []
         
     | 
| 
       17 
17 
     | 
    
         
             
                result = []
         
     | 
| 
       18 
18 
     | 
    
         
             
                old_row_sep = $/
         
     | 
| 
       19 
     | 
    
         
            -
                 
     | 
| 
      
 19 
     | 
    
         
            +
                file_line_count = 0
         
     | 
| 
      
 20 
     | 
    
         
            +
                csv_line_count = 0
         
     | 
| 
       20 
21 
     | 
    
         
             
                begin
         
     | 
| 
       21 
22 
     | 
    
         
             
                  f = input.respond_to?(:readline) ? input : File.open(input, "r:#{options[:file_encoding]}")
         
     | 
| 
       22 
23 
     | 
    
         | 
| 
         @@ -26,14 +27,25 @@ module SmarterCSV 
     | 
|
| 
       26 
27 
     | 
    
         
             
                  end
         
     | 
| 
       27 
28 
     | 
    
         
             
                  $/ = options[:row_sep]
         
     | 
| 
       28 
29 
     | 
    
         | 
| 
      
 30 
     | 
    
         
            +
                  if options[:skip_lines].to_i > 0
         
     | 
| 
      
 31 
     | 
    
         
            +
                    options[:skip_lines].to_i.times{f.readline}
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
       29 
34 
     | 
    
         
             
                  if options[:headers_in_file]        # extract the header line
         
     | 
| 
       30 
35 
     | 
    
         
             
                    # process the header line in the CSV file..
         
     | 
| 
       31 
36 
     | 
    
         
             
                    # the first line of a CSV file contains the header .. it might be commented out, so we need to read it anyhow
         
     | 
| 
       32 
37 
     | 
    
         
             
                    header = f.readline.sub(options[:comment_regexp],'').chomp(options[:row_sep])
         
     | 
| 
       33 
     | 
    
         
            -
                     
     | 
| 
      
 38 
     | 
    
         
            +
                    header = header.encode!('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '') if options[:force_utf8]
         
     | 
| 
      
 39 
     | 
    
         
            +
                    file_line_count += 1
         
     | 
| 
      
 40 
     | 
    
         
            +
                    csv_line_count += 1
         
     | 
| 
       34 
41 
     | 
    
         
             
                    header = header.gsub(options[:strip_chars_from_headers], '') if options[:strip_chars_from_headers]
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
       35 
43 
     | 
    
         
             
                    if (header =~ %r{#{options[:quote_char]}}) and (! options[:force_simple_split])
         
     | 
| 
       36 
     | 
    
         
            -
                      file_headerA =  
     | 
| 
      
 44 
     | 
    
         
            +
                      file_headerA = begin
         
     | 
| 
      
 45 
     | 
    
         
            +
                        CSV.parse( header, csv_options ).flatten.collect!{|x| x.nil? ? '' : x} # to deal with nil values from CSV.parse
         
     | 
| 
      
 46 
     | 
    
         
            +
                      rescue CSV::MalformedCSVError => e
         
     | 
| 
      
 47 
     | 
    
         
            +
                        raise $!, "#{$!} [SmarterCSV: csv line #{csv_line_count}]", $!.backtrace
         
     | 
| 
      
 48 
     | 
    
         
            +
                      end
         
     | 
| 
       37 
49 
     | 
    
         
             
                    else
         
     | 
| 
       38 
50 
     | 
    
         
             
                      file_headerA =  header.split(options[:col_sep])
         
     | 
| 
       39 
51 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -44,11 +56,9 @@ module SmarterCSV 
     | 
|
| 
       44 
56 
     | 
    
         
             
                      file_headerA.map!{|x| x.downcase }   if options[:downcase_header]
         
     | 
| 
       45 
57 
     | 
    
         
             
                    end
         
     | 
| 
       46 
58 
     | 
    
         | 
| 
       47 
     | 
    
         
            -
            #        puts "HeaderA: #{file_headerA.join(' , ')}" if options[:verbose]
         
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
59 
     | 
    
         
             
                    file_header_size = file_headerA.size
         
     | 
| 
       50 
60 
     | 
    
         
             
                  else
         
     | 
| 
       51 
     | 
    
         
            -
                    raise SmarterCSV::IncorrectOption , "ERROR [smarter_csv]: If :headers_in_file is set to false, you have to provide :user_provided_headers" if  
     | 
| 
      
 61 
     | 
    
         
            +
                    raise SmarterCSV::IncorrectOption , "ERROR [smarter_csv]: If :headers_in_file is set to false, you have to provide :user_provided_headers" if options[:user_provided_headers].nil?
         
     | 
| 
       52 
62 
     | 
    
         
             
                  end
         
     | 
| 
       53 
63 
     | 
    
         
             
                  if options[:user_provided_headers] && options[:user_provided_headers].class == Array && ! options[:user_provided_headers].empty?
         
     | 
| 
       54 
64 
     | 
    
         
             
                    # use user-provided headers
         
     | 
| 
         @@ -88,22 +98,30 @@ module SmarterCSV 
     | 
|
| 
       88 
98 
     | 
    
         
             
                  # now on to processing all the rest of the lines in the CSV file:
         
     | 
| 
       89 
99 
     | 
    
         
             
                  while ! f.eof?    # we can't use f.readlines() here, because this would read the whole file into memory at once, and eof => true
         
     | 
| 
       90 
100 
     | 
    
         
             
                    line = f.readline  # read one line.. this uses the input_record_separator $/ which we set previously!
         
     | 
| 
       91 
     | 
    
         
            -
                     
     | 
| 
       92 
     | 
    
         
            -
                     
     | 
| 
      
 101 
     | 
    
         
            +
                    line = line.encode!('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '') if options[:force_utf8]
         
     | 
| 
      
 102 
     | 
    
         
            +
                    file_line_count += 1
         
     | 
| 
      
 103 
     | 
    
         
            +
                    csv_line_count += 1
         
     | 
| 
      
 104 
     | 
    
         
            +
                    print "processing file line %10d, csv line %10d\r" % [file_line_count, csv_line_count] if options[:verbose]
         
     | 
| 
       93 
105 
     | 
    
         
             
                    next  if  line =~ options[:comment_regexp]  # ignore all comment lines if there are any
         
     | 
| 
       94 
106 
     | 
    
         | 
| 
       95 
107 
     | 
    
         
             
                    # cater for the quoted csv data containing the row separator carriage return character
         
     | 
| 
       96 
108 
     | 
    
         
             
                    # in which case the row data will be split across multiple lines (see the sample content in spec/fixtures/carriage_returns_rn.csv)
         
     | 
| 
       97 
109 
     | 
    
         
             
                    # by detecting the existence of an uneven number of quote characters
         
     | 
| 
      
 110 
     | 
    
         
            +
                    multiline = line.count(options[:quote_char])%2 == 1
         
     | 
| 
       98 
111 
     | 
    
         
             
                    while line.count(options[:quote_char])%2 == 1
         
     | 
| 
       99 
     | 
    
         
            -
                      print "line contains uneven number of quote chars so including content of next line" if options[:verbose]
         
     | 
| 
       100 
112 
     | 
    
         
             
                      line += f.readline
         
     | 
| 
      
 113 
     | 
    
         
            +
                      file_line_count += 1
         
     | 
| 
       101 
114 
     | 
    
         
             
                    end
         
     | 
| 
      
 115 
     | 
    
         
            +
                    print "\nline contains uneven number of quote chars so including content through file line %d\n" % file_line_count if options[:verbose] && multiline
         
     | 
| 
       102 
116 
     | 
    
         | 
| 
       103 
117 
     | 
    
         
             
                    line.chomp!    # will use $/ which is set to options[:col_sep]
         
     | 
| 
       104 
118 
     | 
    
         | 
| 
       105 
119 
     | 
    
         
             
                    if (line =~ %r{#{options[:quote_char]}}) and (! options[:force_simple_split])
         
     | 
| 
       106 
     | 
    
         
            -
                      dataA =  
     | 
| 
      
 120 
     | 
    
         
            +
                      dataA = begin
         
     | 
| 
      
 121 
     | 
    
         
            +
                        CSV.parse( line, csv_options ).flatten.collect!{|x| x.nil? ? '' : x} # to deal with nil values from CSV.parse
         
     | 
| 
      
 122 
     | 
    
         
            +
                      rescue CSV::MalformedCSVError => e
         
     | 
| 
      
 123 
     | 
    
         
            +
                        raise $!, "#{$!} [SmarterCSV: csv line #{csv_line_count}]", $!.backtrace
         
     | 
| 
      
 124 
     | 
    
         
            +
                      end
         
     | 
| 
       107 
125 
     | 
    
         
             
                    else
         
     | 
| 
       108 
126 
     | 
    
         
             
                      dataA =  line.split(options[:col_sep])
         
     | 
| 
       109 
127 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -176,6 +194,10 @@ module SmarterCSV 
     | 
|
| 
       176 
194 
     | 
    
         
             
                      end
         
     | 
| 
       177 
195 
     | 
    
         
             
                    end
         
     | 
| 
       178 
196 
     | 
    
         
             
                  end
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
      
 198 
     | 
    
         
            +
                  # print new line to retain last processing line message
         
     | 
| 
      
 199 
     | 
    
         
            +
                  print "\n" if options[:verbose]
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
       179 
201 
     | 
    
         
             
                  # last chunk:
         
     | 
| 
       180 
202 
     | 
    
         
             
                  if ! chunk.nil? && chunk.size > 0
         
     | 
| 
       181 
203 
     | 
    
         
             
                    # do something with the chunk
         
     | 
| 
         @@ -189,6 +211,7 @@ module SmarterCSV 
     | 
|
| 
       189 
211 
     | 
    
         
             
                  end
         
     | 
| 
       190 
212 
     | 
    
         
             
                ensure
         
     | 
| 
       191 
213 
     | 
    
         
             
                  $/ = old_row_sep   # make sure this stupid global variable is always reset to it's previous value after we're done!
         
     | 
| 
      
 214 
     | 
    
         
            +
                  f.close
         
     | 
| 
       192 
215 
     | 
    
         
             
                end
         
     | 
| 
       193 
216 
     | 
    
         
             
                if block_given?
         
     | 
| 
       194 
217 
     | 
    
         
             
                  return chunk_count  # when we do processing through a block we only care how many chunks we processed
         
     | 
| 
         @@ -197,11 +220,6 @@ module SmarterCSV 
     | 
|
| 
       197 
220 
     | 
    
         
             
                end
         
     | 
| 
       198 
221 
     | 
    
         
             
              end
         
     | 
| 
       199 
222 
     | 
    
         | 
| 
       200 
     | 
    
         
            -
            #  def SmarterCSV.process_csv(*args)
         
     | 
| 
       201 
     | 
    
         
            -
            #    warn "[DEPRECATION] `process_csv` is deprecated.  Please use `process` instead."
         
     | 
| 
       202 
     | 
    
         
            -
            #    SmarterCSV.process(*args)
         
     | 
| 
       203 
     | 
    
         
            -
            #  end
         
     | 
| 
       204 
     | 
    
         
            -
             
     | 
| 
       205 
223 
     | 
    
         
             
              private
         
     | 
| 
       206 
224 
     | 
    
         
             
              # acts as a road-block to limit processing when iterating over all k/v pairs of a CSV-hash:
         
     | 
| 
       207 
225 
     | 
    
         | 
| 
         @@ -241,8 +259,7 @@ module SmarterCSV 
     | 
|
| 
       241 
259 
     | 
    
         
             
                end
         
     | 
| 
       242 
260 
     | 
    
         
             
                counts["\r"] += 1 if last_char == "\r"
         
     | 
| 
       243 
261 
     | 
    
         
             
                # find the key/value pair with the largest counter:
         
     | 
| 
       244 
     | 
    
         
            -
                k, 
     | 
| 
      
 262 
     | 
    
         
            +
                k,_ = counts.max_by{|_,v| v}
         
     | 
| 
       245 
263 
     | 
    
         
             
                return k                    # the most frequent one is it
         
     | 
| 
       246 
264 
     | 
    
         
             
              end
         
     | 
| 
       247 
265 
     | 
    
         
             
            end
         
     | 
| 
       248 
     | 
    
         
            -
             
     | 
    
        data/lib/smarter_csv/version.rb
    CHANGED
    
    
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            fixture_path = 'spec/fixtures'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            describe 'be_able_to' do
         
     | 
| 
      
 6 
     | 
    
         
            +
              it 'close file after using it' do
         
     | 
| 
      
 7 
     | 
    
         
            +
                options = {:col_sep => "\cA", :row_sep => "\cB", :comment_regexp => /^#/, :strings_as_keys => true}
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                file = File.new("#{fixture_path}/binary.csv")
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                SmarterCSV.process(file, options)
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                file.closed?.should == true
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            fixture_path = 'spec/fixtures'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            describe 'malformed_csv' do
         
     | 
| 
      
 6 
     | 
    
         
            +
              subject { lambda { SmarterCSV.process(csv_path) } }
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              context "malformed header" do
         
     | 
| 
      
 9 
     | 
    
         
            +
                let(:csv_path) { "#{fixture_path}/malformed_header.csv" }
         
     | 
| 
      
 10 
     | 
    
         
            +
                it { should raise_error(CSV::MalformedCSVError) }
         
     | 
| 
      
 11 
     | 
    
         
            +
                it { should raise_error(/(Missing or stray quote in line 1|CSV::MalformedCSVError)/) }
         
     | 
| 
      
 12 
     | 
    
         
            +
                it { should raise_error(CSV::MalformedCSVError) }
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              context "malformed content" do
         
     | 
| 
      
 16 
     | 
    
         
            +
                let(:csv_path) { "#{fixture_path}/malformed.csv" }
         
     | 
| 
      
 17 
     | 
    
         
            +
                it { should raise_error(CSV::MalformedCSVError) }
         
     | 
| 
      
 18 
     | 
    
         
            +
                it { should raise_error(/(Missing or stray quote in line 1|CSV::MalformedCSVError)/) }
         
     | 
| 
      
 19 
     | 
    
         
            +
                it { should raise_error(CSV::MalformedCSVError) }
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            fixture_path = 'spec/fixtures'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            describe 'be_able_to' do
         
     | 
| 
      
 6 
     | 
    
         
            +
              it 'loads_csv_file_skipping_lines' do
         
     | 
| 
      
 7 
     | 
    
         
            +
                options = {skip_lines: 3}
         
     | 
| 
      
 8 
     | 
    
         
            +
                data = SmarterCSV.process("#{fixture_path}/skip_lines.csv", options)
         
     | 
| 
      
 9 
     | 
    
         
            +
                data.size.should == 4
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                data.each do |item|
         
     | 
| 
      
 12 
     | 
    
         
            +
                  item.keys.each do |key|
         
     | 
| 
      
 13 
     | 
    
         
            +
                    [:first_name,:last_name,:dogs,:cats,:birds,:fish].should include(key)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              it 'loads_csv_with_user_defined_headers' do
         
     | 
| 
      
 19 
     | 
    
         
            +
                options = {:skip_lines => 3, :headers_in_file => true, :user_provided_headers => [:a,:b,:c,:d,:e,:f]}
         
     | 
| 
      
 20 
     | 
    
         
            +
                data = SmarterCSV.process("#{fixture_path}/skip_lines.csv", options)
         
     | 
| 
      
 21 
     | 
    
         
            +
                data.size.should == 4
         
     | 
| 
      
 22 
     | 
    
         
            +
              
         
     | 
| 
      
 23 
     | 
    
         
            +
                data.each do |item|
         
     | 
| 
      
 24 
     | 
    
         
            +
                  item.keys.each do |key|
         
     | 
| 
      
 25 
     | 
    
         
            +
                    [:a,:b,:c,:d,:e,:f].should include( key )
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: smarter_csv
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 1.1. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 1.1.1
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - |
         
     | 
| 
         @@ -9,7 +9,7 @@ authors: 
     | 
|
| 
       9 
9 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       10 
10 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       11 
11 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       12 
     | 
    
         
            -
            date:  
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2016-11-26 00:00:00.000000000 Z
         
     | 
| 
       13 
13 
     | 
    
         
             
            dependencies:
         
     | 
| 
       14 
14 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       15 
15 
     | 
    
         
             
              name: rspec
         
     | 
| 
         @@ -59,18 +59,22 @@ files: 
     | 
|
| 
       59 
59 
     | 
    
         
             
            - spec/fixtures/line_endings_r.csv
         
     | 
| 
       60 
60 
     | 
    
         
             
            - spec/fixtures/line_endings_rn.csv
         
     | 
| 
       61 
61 
     | 
    
         
             
            - spec/fixtures/lots_of_columns.csv
         
     | 
| 
      
 62 
     | 
    
         
            +
            - spec/fixtures/malformed.csv
         
     | 
| 
      
 63 
     | 
    
         
            +
            - spec/fixtures/malformed_header.csv
         
     | 
| 
       62 
64 
     | 
    
         
             
            - spec/fixtures/money.csv
         
     | 
| 
       63 
65 
     | 
    
         
             
            - spec/fixtures/no_header.csv
         
     | 
| 
       64 
66 
     | 
    
         
             
            - spec/fixtures/numeric.csv
         
     | 
| 
       65 
67 
     | 
    
         
             
            - spec/fixtures/pets.csv
         
     | 
| 
       66 
68 
     | 
    
         
             
            - spec/fixtures/quoted.csv
         
     | 
| 
       67 
69 
     | 
    
         
             
            - spec/fixtures/separator.csv
         
     | 
| 
      
 70 
     | 
    
         
            +
            - spec/fixtures/skip_lines.csv
         
     | 
| 
       68 
71 
     | 
    
         
             
            - spec/fixtures/with_dashes.csv
         
     | 
| 
       69 
72 
     | 
    
         
             
            - spec/fixtures/with_dates.csv
         
     | 
| 
       70 
73 
     | 
    
         
             
            - spec/smarter_csv/binary_file2_spec.rb
         
     | 
| 
       71 
74 
     | 
    
         
             
            - spec/smarter_csv/binary_file_spec.rb
         
     | 
| 
       72 
75 
     | 
    
         
             
            - spec/smarter_csv/carriage_return_spec.rb
         
     | 
| 
       73 
76 
     | 
    
         
             
            - spec/smarter_csv/chunked_reading_spec.rb
         
     | 
| 
      
 77 
     | 
    
         
            +
            - spec/smarter_csv/close_file_spec.rb
         
     | 
| 
       74 
78 
     | 
    
         
             
            - spec/smarter_csv/column_separator_spec.rb
         
     | 
| 
       75 
79 
     | 
    
         
             
            - spec/smarter_csv/convert_values_to_numeric_spec.rb
         
     | 
| 
       76 
80 
     | 
    
         
             
            - spec/smarter_csv/header_transformation_spec.rb
         
     | 
| 
         @@ -78,6 +82,7 @@ files: 
     | 
|
| 
       78 
82 
     | 
    
         
             
            - spec/smarter_csv/key_mapping_spec.rb
         
     | 
| 
       79 
83 
     | 
    
         
             
            - spec/smarter_csv/line_ending_spec.rb
         
     | 
| 
       80 
84 
     | 
    
         
             
            - spec/smarter_csv/load_basic_spec.rb
         
     | 
| 
      
 85 
     | 
    
         
            +
            - spec/smarter_csv/malformed_spec.rb
         
     | 
| 
       81 
86 
     | 
    
         
             
            - spec/smarter_csv/no_header_spec.rb
         
     | 
| 
       82 
87 
     | 
    
         
             
            - spec/smarter_csv/not_downcase_header_spec.rb
         
     | 
| 
       83 
88 
     | 
    
         
             
            - spec/smarter_csv/quoted_spec.rb
         
     | 
| 
         @@ -86,6 +91,7 @@ files: 
     | 
|
| 
       86 
91 
     | 
    
         
             
            - spec/smarter_csv/remove_not_mapped_keys_spec.rb
         
     | 
| 
       87 
92 
     | 
    
         
             
            - spec/smarter_csv/remove_values_matching_spec.rb
         
     | 
| 
       88 
93 
     | 
    
         
             
            - spec/smarter_csv/remove_zero_values_spec.rb
         
     | 
| 
      
 94 
     | 
    
         
            +
            - spec/smarter_csv/skip_lines_spec.rb
         
     | 
| 
       89 
95 
     | 
    
         
             
            - spec/smarter_csv/strings_as_keys_spec.rb
         
     | 
| 
       90 
96 
     | 
    
         
             
            - spec/smarter_csv/strip_chars_from_headers_spec.rb
         
     | 
| 
       91 
97 
     | 
    
         
             
            - spec/smarter_csv/value_converters_spec.rb
         
     | 
| 
         @@ -132,18 +138,22 @@ test_files: 
     | 
|
| 
       132 
138 
     | 
    
         
             
            - spec/fixtures/line_endings_r.csv
         
     | 
| 
       133 
139 
     | 
    
         
             
            - spec/fixtures/line_endings_rn.csv
         
     | 
| 
       134 
140 
     | 
    
         
             
            - spec/fixtures/lots_of_columns.csv
         
     | 
| 
      
 141 
     | 
    
         
            +
            - spec/fixtures/malformed.csv
         
     | 
| 
      
 142 
     | 
    
         
            +
            - spec/fixtures/malformed_header.csv
         
     | 
| 
       135 
143 
     | 
    
         
             
            - spec/fixtures/money.csv
         
     | 
| 
       136 
144 
     | 
    
         
             
            - spec/fixtures/no_header.csv
         
     | 
| 
       137 
145 
     | 
    
         
             
            - spec/fixtures/numeric.csv
         
     | 
| 
       138 
146 
     | 
    
         
             
            - spec/fixtures/pets.csv
         
     | 
| 
       139 
147 
     | 
    
         
             
            - spec/fixtures/quoted.csv
         
     | 
| 
       140 
148 
     | 
    
         
             
            - spec/fixtures/separator.csv
         
     | 
| 
      
 149 
     | 
    
         
            +
            - spec/fixtures/skip_lines.csv
         
     | 
| 
       141 
150 
     | 
    
         
             
            - spec/fixtures/with_dashes.csv
         
     | 
| 
       142 
151 
     | 
    
         
             
            - spec/fixtures/with_dates.csv
         
     | 
| 
       143 
152 
     | 
    
         
             
            - spec/smarter_csv/binary_file2_spec.rb
         
     | 
| 
       144 
153 
     | 
    
         
             
            - spec/smarter_csv/binary_file_spec.rb
         
     | 
| 
       145 
154 
     | 
    
         
             
            - spec/smarter_csv/carriage_return_spec.rb
         
     | 
| 
       146 
155 
     | 
    
         
             
            - spec/smarter_csv/chunked_reading_spec.rb
         
     | 
| 
      
 156 
     | 
    
         
            +
            - spec/smarter_csv/close_file_spec.rb
         
     | 
| 
       147 
157 
     | 
    
         
             
            - spec/smarter_csv/column_separator_spec.rb
         
     | 
| 
       148 
158 
     | 
    
         
             
            - spec/smarter_csv/convert_values_to_numeric_spec.rb
         
     | 
| 
       149 
159 
     | 
    
         
             
            - spec/smarter_csv/header_transformation_spec.rb
         
     | 
| 
         @@ -151,6 +161,7 @@ test_files: 
     | 
|
| 
       151 
161 
     | 
    
         
             
            - spec/smarter_csv/key_mapping_spec.rb
         
     | 
| 
       152 
162 
     | 
    
         
             
            - spec/smarter_csv/line_ending_spec.rb
         
     | 
| 
       153 
163 
     | 
    
         
             
            - spec/smarter_csv/load_basic_spec.rb
         
     | 
| 
      
 164 
     | 
    
         
            +
            - spec/smarter_csv/malformed_spec.rb
         
     | 
| 
       154 
165 
     | 
    
         
             
            - spec/smarter_csv/no_header_spec.rb
         
     | 
| 
       155 
166 
     | 
    
         
             
            - spec/smarter_csv/not_downcase_header_spec.rb
         
     | 
| 
       156 
167 
     | 
    
         
             
            - spec/smarter_csv/quoted_spec.rb
         
     | 
| 
         @@ -159,6 +170,7 @@ test_files: 
     | 
|
| 
       159 
170 
     | 
    
         
             
            - spec/smarter_csv/remove_not_mapped_keys_spec.rb
         
     | 
| 
       160 
171 
     | 
    
         
             
            - spec/smarter_csv/remove_values_matching_spec.rb
         
     | 
| 
       161 
172 
     | 
    
         
             
            - spec/smarter_csv/remove_zero_values_spec.rb
         
     | 
| 
      
 173 
     | 
    
         
            +
            - spec/smarter_csv/skip_lines_spec.rb
         
     | 
| 
       162 
174 
     | 
    
         
             
            - spec/smarter_csv/strings_as_keys_spec.rb
         
     | 
| 
       163 
175 
     | 
    
         
             
            - spec/smarter_csv/strip_chars_from_headers_spec.rb
         
     | 
| 
       164 
176 
     | 
    
         
             
            - spec/smarter_csv/value_converters_spec.rb
         
     |