smarter_csv 1.3.0 → 1.5.0
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/.gitignore +2 -0
- data/CHANGELOG.md +181 -0
- data/CONTRIBUTORS.md +46 -0
- data/LICENSE.txt +21 -0
- data/README.md +50 -239
- data/Rakefile +8 -15
- data/lib/smarter_csv/smarter_csv.rb +114 -38
- data/lib/smarter_csv/version.rb +1 -1
- data/lib/smarter_csv.rb +8 -0
- data/smarter_csv.gemspec +20 -16
- data/spec/fixtures/additional_separator.csv +6 -0
- data/spec/fixtures/empty_columns_1.csv +2 -0
- data/spec/fixtures/empty_columns_2.csv +2 -0
- data/spec/fixtures/hard_sample.csv +2 -0
- data/spec/fixtures/numeric.csv +1 -1
- data/spec/fixtures/separator_colon.csv +4 -0
- data/spec/fixtures/separator_comma.csv +4 -0
- data/spec/fixtures/separator_pipe.csv +4 -0
- data/spec/fixtures/{separator.csv → separator_semi.csv} +0 -0
- data/spec/fixtures/separator_tab.csv +4 -0
- data/spec/smarter_csv/additional_separator_spec.rb +45 -0
- data/spec/smarter_csv/binary_file2_spec.rb +1 -1
- data/spec/smarter_csv/blank_spec.rb +55 -0
- data/spec/smarter_csv/carriage_return_spec.rb +27 -7
- data/spec/smarter_csv/column_separator_spec.rb +89 -5
- data/spec/smarter_csv/empty_columns_spec.rb +74 -0
- data/spec/smarter_csv/hard_sample_spec.rb +24 -0
- data/spec/smarter_csv/ignore_comments_spec.rb +45 -30
- metadata +50 -13
    
        data/README.md
    CHANGED
    
    | @@ -1,19 +1,24 @@ | |
| 1 | 
            -
            # SmarterCSV
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            [](http://travis-ci.org/tilo/smarter_csv) [](http://badge.fury.io/rb/smarter_csv)
         | 
| 4 1 |  | 
| 5 | 
            -
            ---------------
         | 
| 6 2 | 
             
            #### Service Announcement
         | 
| 7 3 |  | 
| 8 | 
            -
            Work towards SmarterCSV 2.0 is on it's way, with much improved features, and more streamlined options.
         | 
| 4 | 
            +
            * Work towards SmarterCSV 2.0 is still on it's way, with much improved features, and more streamlined options.
         | 
| 5 | 
            +
              Please check the [2.0-develop branch](https://github.com/tilo/smarter_csv/blob/master/README.md), open any issues and pull requests with mention of v2.0.
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            * New versions of SmarterCSV 1.x will soon print a deprecation warning if you set :verbose to true
         | 
| 8 | 
            +
              See below for list of deprecated options.
         | 
| 9 9 |  | 
| 10 | 
            -
             | 
| 10 | 
            +
            #### Restructured Branches
         | 
| 11 11 |  | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 12 | 
            +
            * default branch is `main` for 1.x development
         | 
| 13 | 
            +
            * 2.x development is on `2.0-development`
         | 
| 14 14 |  | 
| 15 15 | 
             
            ---------------
         | 
| 16 | 
            -
             | 
| 16 | 
            +
             | 
| 17 | 
            +
            # SmarterCSV
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            [](http://travis-ci.org/tilo/smarter_csv) [](http://badge.fury.io/rb/smarter_csv)
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            #### SmarterCSV 1.x
         | 
| 17 22 |  | 
| 18 23 | 
             
            `smarter_csv` is a Ruby Gem for smarter importing of CSV Files as Array(s) of Hashes, suitable for direct processing with Mongoid or ActiveRecord,
         | 
| 19 24 | 
             
            and parallel processing with Resque or Sidekiq.
         | 
| @@ -56,6 +61,7 @@ You can also set the `:row_sep` manually! Checkout Example 5 for unusual `:row_s | |
| 56 61 | 
             
            #### Example 1a: How SmarterCSV processes CSV-files as array of hashes:
         | 
| 57 62 | 
             
            Please note how each hash contains only the keys for columns with non-null values.
         | 
| 58 63 |  | 
| 64 | 
            +
            ```ruby
         | 
| 59 65 | 
             
                 $ cat pets.csv
         | 
| 60 66 | 
             
                 first name,last name,dogs,cats,birds,fish
         | 
| 61 67 | 
             
                 Dan,McAllister,2,,,
         | 
| @@ -71,21 +77,25 @@ Please note how each hash contains only the keys for columns with non-null value | |
| 71 77 | 
             
                       {:first_name=>"Miles", :last_name=>"O'Brian", :fish=>"21"},
         | 
| 72 78 | 
             
                       {:first_name=>"Nancy", :last_name=>"Homes", :dogs=>"2", :birds=>"1"}
         | 
| 73 79 | 
             
                     ]
         | 
| 80 | 
            +
            ```
         | 
| 74 81 |  | 
| 75 82 |  | 
| 76 83 | 
             
            #### Example 1b: How SmarterCSV processes CSV-files as chunks, returning arrays of hashes:
         | 
| 77 84 | 
             
            Please note how the returned array contains two sub-arrays containing the chunks which were read, each chunk containing 2 hashes.
         | 
| 78 85 | 
             
            In case the number of rows is not cleanly divisible by `:chunk_size`, the last chunk contains fewer hashes.
         | 
| 79 86 |  | 
| 87 | 
            +
            ```ruby
         | 
| 80 88 | 
             
                 > pets_by_owner = SmarterCSV.process('/tmp/pets.csv', {:chunk_size => 2, :key_mapping => {:first_name => :first, :last_name => :last}})
         | 
| 81 89 | 
             
                   => [ [ {:first=>"Dan", :last=>"McAllister", :dogs=>"2"}, {:first=>"Lucy", :last=>"Laweless", :cats=>"5"} ],
         | 
| 82 90 | 
             
                        [ {:first=>"Miles", :last=>"O'Brian", :fish=>"21"}, {:first=>"Nancy", :last=>"Homes", :dogs=>"2", :birds=>"1"} ]
         | 
| 83 91 | 
             
                      ]
         | 
| 92 | 
            +
            ```
         | 
| 84 93 |  | 
| 85 94 | 
             
            #### Example 1c: How SmarterCSV processes CSV-files as chunks, and passes arrays of hashes to a given block:
         | 
| 86 95 | 
             
            Please note how the given block is passed the data for each chunk as the parameter (array of hashes),
         | 
| 87 96 | 
             
            and how the `process` method returns the number of chunks when called with a block
         | 
| 88 97 |  | 
| 98 | 
            +
            ```ruby
         | 
| 89 99 | 
             
                 > total_chunks = SmarterCSV.process('/tmp/pets.csv', {:chunk_size => 2, :key_mapping => {:first_name => :first, :last_name => :last}}) do |chunk|
         | 
| 90 100 | 
             
                     chunk.each do |h|   # you can post-process the data from each row to your heart's content, and also create virtual attributes:
         | 
| 91 101 | 
             
                       h[:full_name] = [h[:first],h[:last]].join(' ')  # create a virtual attribute
         | 
| @@ -97,16 +107,16 @@ and how the `process` method returns the number of chunks when called with a blo | |
| 97 107 | 
             
                   [{:dogs=>"2", :full_name=>"Dan McAllister"}, {:cats=>"5", :full_name=>"Lucy Laweless"}]
         | 
| 98 108 | 
             
                   [{:fish=>"21", :full_name=>"Miles O'Brian"}, {:dogs=>"2", :birds=>"1", :full_name=>"Nancy Homes"}]
         | 
| 99 109 | 
             
                    => 2
         | 
| 100 | 
            -
             | 
| 110 | 
            +
            ```
         | 
| 101 111 | 
             
            #### Example 2: Reading a CSV-File in one Chunk, returning one Array of Hashes:
         | 
| 102 | 
            -
             | 
| 112 | 
            +
            ```ruby
         | 
| 103 113 | 
             
                filename = '/tmp/input_file.txt' # TAB delimited file, each row ending with Control-M
         | 
| 104 114 | 
             
                recordsA = SmarterCSV.process(filename, {:col_sep => "\t", :row_sep => "\cM"})  # no block given
         | 
| 105 115 |  | 
| 106 116 | 
             
                => returns an array of hashes
         | 
| 107 | 
            -
             | 
| 117 | 
            +
            ```
         | 
| 108 118 | 
             
            #### Example 3: Populate a MySQL or MongoDB Database with SmarterCSV:
         | 
| 109 | 
            -
             | 
| 119 | 
            +
            ```ruby
         | 
| 110 120 | 
             
                # without using chunks:
         | 
| 111 121 | 
             
                filename = '/tmp/some.csv'
         | 
| 112 122 | 
             
                options = {:key_mapping => {:unwanted_row => nil, :old_row_name => :new_name}}
         | 
| @@ -117,9 +127,9 @@ and how the `process` method returns the number of chunks when called with a blo | |
| 117 127 | 
             
                end
         | 
| 118 128 |  | 
| 119 129 | 
             
                 => returns number of chunks / rows we processed
         | 
| 120 | 
            -
             | 
| 130 | 
            +
            ```
         | 
| 121 131 | 
             
            #### Example 4: Populate a MongoDB Database in Chunks of 100 records with SmarterCSV:
         | 
| 122 | 
            -
             | 
| 132 | 
            +
            ```ruby
         | 
| 123 133 | 
             
                # using chunks:
         | 
| 124 134 | 
             
                filename = '/tmp/some.csv'
         | 
| 125 135 | 
             
                options = {:chunk_size => 100, :key_mapping => {:unwanted_row => nil, :old_row_name => :new_name}}
         | 
| @@ -130,10 +140,10 @@ and how the `process` method returns the number of chunks when called with a blo | |
| 130 140 | 
             
                end
         | 
| 131 141 |  | 
| 132 142 | 
             
                 => returns number of chunks we processed
         | 
| 133 | 
            -
             | 
| 143 | 
            +
            ```
         | 
| 134 144 |  | 
| 135 145 | 
             
            #### Example 5: Reading a CSV-like File, and Processing it with Resque:
         | 
| 136 | 
            -
             | 
| 146 | 
            +
            ```ruby
         | 
| 137 147 | 
             
                filename = '/tmp/strange_db_dump'   # a file with CRTL-A as col_separator, and with CTRL-B\n as record_separator (hello iTunes!)
         | 
| 138 148 | 
             
                options = {
         | 
| 139 149 | 
             
                  :col_sep => "\cA", :row_sep => "\cB\n", :comment_regexp => /^#/,
         | 
| @@ -143,11 +153,11 @@ and how the `process` method returns the number of chunks when called with a blo | |
| 143 153 | 
             
                    Resque.enque( ResqueWorkerClass, chunk ) # pass chunks of CSV-data to Resque workers for parallel processing
         | 
| 144 154 | 
             
                end
         | 
| 145 155 | 
             
                => returns number of chunks
         | 
| 146 | 
            -
             | 
| 156 | 
            +
            ```
         | 
| 147 157 | 
             
            #### Example 6: Using Value Converters
         | 
| 148 158 |  | 
| 149 159 | 
             
            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.
         | 
| 150 | 
            -
             | 
| 160 | 
            +
            ```ruby
         | 
| 151 161 | 
             
                $ cat spec/fixtures/with_dates.csv
         | 
| 152 162 | 
             
                first,last,date,price
         | 
| 153 163 | 
             
                Ben,Miller,10/30/1998,$44.50
         | 
| @@ -180,7 +190,7 @@ NOTE: If you use `key_mappings` and `value_converters`, make sure that the value | |
| 180 190 | 
             
                  => 44.50
         | 
| 181 191 | 
             
                data[0][:price].class
         | 
| 182 192 | 
             
                  => Float
         | 
| 183 | 
            -
             | 
| 193 | 
            +
            ```
         | 
| 184 194 | 
             
            ## Parallel Processing
         | 
| 185 195 | 
             
            [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)
         | 
| 186 196 |  | 
| @@ -205,9 +215,9 @@ The options and the block are optional. | |
| 205 215 | 
             
                 | :invalid_byte_sequence      |   ''     | what to replace invalid byte sequences with                                          |
         | 
| 206 216 | 
             
                 | :force_utf8                 |   false  | force UTF-8 encoding of all lines (including headers) in the CSV file                |
         | 
| 207 217 | 
             
                 | :skip_lines                 |   nil    | how many lines to skip before the first line or header line is processed             |
         | 
| 208 | 
            -
                 | :comment_regexp             |    | 
| 218 | 
            +
                 | :comment_regexp             |   nil    | regular expression to ignore comment lines (see NOTE on CSV header), e.g./\A#/       |
         | 
| 209 219 | 
             
                 ---------------------------------------------------------------------------------------------------------------------------------
         | 
| 210 | 
            -
                 | :col_sep                    |   ','    | column separator | 
| 220 | 
            +
                 | :col_sep                    |   ','    | column separator, can be set to :auto                                                |
         | 
| 211 221 | 
             
                 | :force_simple_split         |   false  | force simple splitting on :col_sep character for non-standard CSV-files.             |
         | 
| 212 222 | 
             
                 |                             |          | e.g. when :quote_char is not properly escaped                                        |
         | 
| 213 223 | 
             
                 | :row_sep                    | $/ ,"\n" | row separator or record separator , defaults to system's $/ , which defaults to "\n" |
         | 
| @@ -222,7 +232,7 @@ The options and the block are optional. | |
| 222 232 | 
             
                 |                             |          | user provided Array of header strings or symbols, to define                          |
         | 
| 223 233 | 
             
                 |                             |          | what headers should be used, overriding any in-file headers.                         |
         | 
| 224 234 | 
             
                 |                             |          | You can not combine the :user_provided_headers and :key_mapping options              |
         | 
| 225 | 
            -
                 | :remove_empty_hashes        |   true   | remove / ignore any hashes which don't have any key/value pairs | 
| 235 | 
            +
                 | :remove_empty_hashes        |   true   | remove / ignore any hashes which don't have any key/value pairs or all empty values  |
         | 
| 226 236 | 
             
                 | :verbose                    |   false  | print out line number while processing (to track down problems in input files)       |
         | 
| 227 237 | 
             
                 ---------------------------------------------------------------------------------------------------------------------------------
         | 
| 228 238 |  | 
| @@ -248,7 +258,7 @@ And header and data validations will also be supported in 2.x | |
| 248 258 | 
             
                 ---------------------------------------------------------------------------------------------------------------------------------
         | 
| 249 259 | 
             
                 | :value_converters           |   nil    | supply a hash of :header => KlassName; the class needs to implement self.convert(val)|
         | 
| 250 260 | 
             
                 | :remove_empty_values        |   true   | remove values which have nil or empty strings as values                              |
         | 
| 251 | 
            -
                 | :remove_zero_values         |    | 
| 261 | 
            +
                 | :remove_zero_values         |   false  | remove values which have a numeric value equal to zero / 0                           |
         | 
| 252 262 | 
             
                 | :remove_values_matching     |   nil    | removes key/value pairs if value matches given regular expressions. e.g.:            |
         | 
| 253 263 | 
             
                 |                             |          | /^\$0\.0+$/ to match $0.00 , or /^#VALUE!$/ to match errors in Excel spreadsheets    |
         | 
| 254 264 | 
             
                 | :convert_values_to_numeric  |   true   | converts strings containing Integers or Floats to the appropriate class              |
         | 
| @@ -259,22 +269,23 @@ And header and data validations will also be supported in 2.x | |
| 259 269 | 
             
            #### NOTES about File Encodings:
         | 
| 260 270 | 
             
             * if you have a CSV file which contains unicode characters, you can process it as follows:
         | 
| 261 271 |  | 
| 262 | 
            -
             | 
| 272 | 
            +
            ```ruby
         | 
| 263 273 | 
             
                   File.open(filename, "r:bom|utf-8") do |f|
         | 
| 264 274 | 
             
                     data = SmarterCSV.process(f);
         | 
| 265 275 | 
             
                   end
         | 
| 266 | 
            -
             | 
| 276 | 
            +
            ```
         | 
| 267 277 | 
             
            * if the CSV file with unicode characters is in a remote location, similarly you need to give the encoding as an option to the `open` call:
         | 
| 268 | 
            -
             | 
| 278 | 
            +
            ```ruby
         | 
| 269 279 | 
             
                   require 'open-uri'
         | 
| 270 280 | 
             
                   file_location = 'http://your.remote.org/sample.csv'
         | 
| 271 281 | 
             
                   open(file_location, 'r:utf-8') do |f|   # don't forget to specify the UTF-8 encoding!!
         | 
| 272 282 | 
             
                     data = SmarterCSV.process(f)
         | 
| 273 283 | 
             
                   end
         | 
| 274 | 
            -
             | 
| 284 | 
            +
            ```
         | 
| 275 285 | 
             
            #### NOTES about CSV Headers:
         | 
| 276 286 | 
             
             * as this method parses CSV files, it is assumed that the first line of any file will contain a valid header
         | 
| 277 | 
            -
             * the first line with the  | 
| 287 | 
            +
             * the first line with the header might be commented out, in which case you will need to set `comment_regexp: /\A#/`
         | 
| 288 | 
            +
               This is no longer handled automatically since 1.5.0.
         | 
| 278 289 | 
             
             * any occurences of :comment_regexp or :row_sep will be stripped from the first line with the CSV header
         | 
| 279 290 | 
             
             * any of the keys in the header line will be downcased, spaces replaced by underscore, and converted to Ruby symbols before being used as keys in the returned Hashes
         | 
| 280 291 | 
             
             * you can not combine the :user_provided_headers and :key_mapping options
         | 
| @@ -305,227 +316,27 @@ And header and data validations will also be supported in 2.x | |
| 305 316 | 
             
            ## Installation
         | 
| 306 317 |  | 
| 307 318 | 
             
            Add this line to your application's Gemfile:
         | 
| 308 | 
            -
             | 
| 319 | 
            +
            ```ruby
         | 
| 309 320 | 
             
                gem 'smarter_csv'
         | 
| 310 | 
            -
             | 
| 321 | 
            +
            ```
         | 
| 311 322 | 
             
            And then execute:
         | 
| 312 | 
            -
             | 
| 323 | 
            +
            ```ruby
         | 
| 313 324 | 
             
                $ bundle
         | 
| 314 | 
            -
             | 
| 325 | 
            +
            ```
         | 
| 315 326 | 
             
            Or install it yourself as:
         | 
| 316 | 
            -
             | 
| 327 | 
            +
            ```ruby
         | 
| 317 328 | 
             
                $ gem install smarter_csv
         | 
| 318 | 
            -
             | 
| 319 | 
            -
            ##  | 
| 320 | 
            -
             | 
| 321 | 
            -
            Planned in the next releases:
         | 
| 322 | 
            -
             * programmatic header transformations
         | 
| 323 | 
            -
             * CSV command line
         | 
| 324 | 
            -
             | 
| 325 | 
            -
            ## Changes
         | 
| 326 | 
            -
             | 
| 327 | 
            -
            #### 1.3.0 (2022-01-06) Breaking code change if you used `--key_mappings`
         | 
| 328 | 
            -
             * fix bug for key_mappings (issue #181)   
         | 
| 329 | 
            -
               The values of the `key_mappings` hash will now be used "as is", and no longer forced to be symbols
         | 
| 330 | 
            -
             | 
| 331 | 
            -
               **Users with existing code with `--key_mappings` need to change their code** to 
         | 
| 332 | 
            -
                 * either use symbols in the `key_mapping` hash
         | 
| 333 | 
            -
                 * or change the expected keys from symbols to strings
         | 
| 334 | 
            -
             | 
| 335 | 
            -
            #### 1.2.9 (2021-11-22) (PULLED)
         | 
| 336 | 
            -
             * fix bug for key_mappings (issue #181)
         | 
| 337 | 
            -
               The values of the `key_mappings` hash will now be used "as is", and no longer forced to be symbols
         | 
| 338 | 
            -
             | 
| 339 | 
            -
            #### 1.2.8 (2020-02-04)
         | 
| 340 | 
            -
             * fix deprecation warnings on Ruby 2.7 (thank to Diego Salido)
         | 
| 341 | 
            -
             | 
| 342 | 
            -
            #### 1.2.7 (2020-02-03)
         | 
| 343 | 
            -
             | 
| 344 | 
            -
            #### 1.2.6 (2018-11-13)
         | 
| 345 | 
            -
             * fixing error caused by calling f.close when we do not hand in a file
         | 
| 346 | 
            -
             | 
| 347 | 
            -
            #### 1.2.5 (2018-09-16)
         | 
| 348 | 
            -
             * fixing issue #136 with comments in CSV files
         | 
| 349 | 
            -
             * fixing error class hierarchy
         | 
| 350 | 
            -
             | 
| 351 | 
            -
            #### 1.2.4 (2018-08-06)
         | 
| 352 | 
            -
             * using Rails blank? if it's available
         | 
| 353 | 
            -
             | 
| 354 | 
            -
            #### 1.2.3 (2018-01-27)
         | 
| 355 | 
            -
             * fixed regression / test
         | 
| 356 | 
            -
             * fuxed quote_char interpolation for headers, but not data (thanks to Colin Petruno)
         | 
| 357 | 
            -
             * bugfix (thanks to Joshua Smith for reporting)
         | 
| 358 | 
            -
             | 
| 359 | 
            -
            #### 1.2.0 (2018-01-20)
         | 
| 360 | 
            -
             * add default validation that a header can only appear once
         | 
| 361 | 
            -
             * add option `required_headers`
         | 
| 362 | 
            -
             | 
| 363 | 
            -
            #### 1.1.5 (2017-11-05)
         | 
| 364 | 
            -
             * fix issue with invalid byte sequences in header (issue #103, thanks to Dave Myron)
         | 
| 365 | 
            -
             * fix issue with invalid byte sequences in multi-line data (thanks to Ivan Ushakov)
         | 
| 366 | 
            -
             * analyze only 500 characters by default when `:row_sep => :auto` is used.
         | 
| 367 | 
            -
               added option `row_sep_auto_chars` to change the default if necessary. (thanks to Matthieu Paret)
         | 
| 368 | 
            -
             | 
| 369 | 
            -
            #### 1.1.4 (2017-01-16)
         | 
| 370 | 
            -
             * fixing UTF-8 related bug which was introduced in 1.1.2 (thanks to Tirdad C.)
         | 
| 371 | 
            -
             | 
| 372 | 
            -
            #### 1.1.3 (2016-12-30)
         | 
| 373 | 
            -
             * added warning when options indicate UTF-8 processing, but input filehandle is not opened with r:UTF-8 option
         | 
| 374 | 
            -
             | 
| 375 | 
            -
            #### 1.1.2 (2016-12-29)
         | 
| 376 | 
            -
             * added option `invalid_byte_sequence` (thanks to polycarpou)
         | 
| 377 | 
            -
             * added comments on handling of UTF-8 encoding when opening from File vs. OpenURI (thanks to KevinColemanInc)
         | 
| 378 | 
            -
             | 
| 379 | 
            -
            #### 1.1.1 (2016-11-26)
         | 
| 380 | 
            -
             * added option to `skip_lines` (thanks to wal)
         | 
| 381 | 
            -
             * added option to `force_utf8` encoding (thanks to jordangraft)
         | 
| 382 | 
            -
             * bugfix if no headers in input data (thanks to esBeee)
         | 
| 383 | 
            -
             * ensure input file is closed (thanks to waldyr)
         | 
| 384 | 
            -
             * improved verbose output (thankd to benmaher)
         | 
| 385 | 
            -
             * improved documentation
         | 
| 386 | 
            -
             | 
| 387 | 
            -
            #### 1.1.0 (2015-07-26)
         | 
| 388 | 
            -
             * added feature :value_converters, which allows parsing of dates, money, and other things (thanks to Raphaël Bleuse, Lucas Camargo de Almeida, Alejandro)
         | 
| 389 | 
            -
             * added error if :headers_in_file is set to false, and no :user_provided_headers are given (thanks to innhyu)
         | 
| 390 | 
            -
             * added support to convert dashes to underscore characters in headers (thanks to César Camacho)
         | 
| 391 | 
            -
             * fixing automatic detection of \r\n line-endings (thanks to feens)
         | 
| 392 | 
            -
             | 
| 393 | 
            -
            #### 1.0.19 (2014-10-29)
         | 
| 394 | 
            -
             * added option :keep_original_headers to keep CSV-headers as-is (thanks to Benjamin Thouret)
         | 
| 395 | 
            -
             | 
| 396 | 
            -
            #### 1.0.18 (2014-10-27)
         | 
| 397 | 
            -
             * added support for multi-line fields / csv fields containing CR (thanks to Chris Hilton) (issue #31)
         | 
| 398 | 
            -
             | 
| 399 | 
            -
            #### 1.0.17 (2014-01-13)
         | 
| 400 | 
            -
             * added option to set :row_sep to :auto , for automatic detection of the row-separator (issue #22)
         | 
| 401 | 
            -
             | 
| 402 | 
            -
            #### 1.0.16 (2014-01-13)
         | 
| 403 | 
            -
             * :convert_values_to_numeric option can now be qualified with :except or :only (thanks to Hugo Lepetit)
         | 
| 404 | 
            -
             * removed deprecated `process_csv` method
         | 
| 405 | 
            -
             | 
| 406 | 
            -
            #### 1.0.15 (2013-12-07)
         | 
| 407 | 
            -
             * new option:
         | 
| 408 | 
            -
               * :remove_unmapped_keys  to completely ignore columns which were not mapped with :key_mapping (thanks to Dave Sanders)
         | 
| 409 | 
            -
             | 
| 410 | 
            -
            #### 1.0.14 (2013-11-01)
         | 
| 411 | 
            -
             * added GPL-2 and MIT license to GEM spec file; if you need another license contact me
         | 
| 412 | 
            -
             | 
| 413 | 
            -
            #### 1.0.12 (2013-10-15)
         | 
| 414 | 
            -
             * added RSpec tests
         | 
| 415 | 
            -
             | 
| 416 | 
            -
            #### 1.0.11 (2013-09-28)
         | 
| 417 | 
            -
             * bugfix : fixed issue #18 - fixing issue with last chunk not being properly returned (thanks to Jordan Running)
         | 
| 418 | 
            -
             * added RSpec tests
         | 
| 419 | 
            -
             | 
| 420 | 
            -
            #### 1.0.10 (2013-06-26)
         | 
| 421 | 
            -
             * bugfix : fixed issue #14 - passing options along to CSV.parse (thanks to Marcos Zimmermann)
         | 
| 422 | 
            -
             | 
| 423 | 
            -
            #### 1.0.9 (2013-06-19)
         | 
| 424 | 
            -
             * bugfix : fixed issue #13 with negative integers and floats not being correctly converted (thanks to Graham Wetzler)
         | 
| 425 | 
            -
             | 
| 426 | 
            -
            #### 1.0.8 (2013-06-01)
         | 
| 427 | 
            -
             | 
| 428 | 
            -
             * bugfix : fixed issue with nil values in inputs with quote-char (thanks to Félix Bellanger)
         | 
| 429 | 
            -
             * new options:
         | 
| 430 | 
            -
                * :force_simple_split : to force simiple splitting on :col_sep character for non-standard CSV-files. e.g. without properly escaped :quote_char
         | 
| 431 | 
            -
                * :verbose : print out line number while processing (to track down problems in input files)
         | 
| 432 | 
            -
             | 
| 433 | 
            -
            #### 1.0.7 (2013-05-20)
         | 
| 434 | 
            -
             | 
| 435 | 
            -
             * allowing process to work with objects with a 'readline' method (thanks to taq)
         | 
| 436 | 
            -
             * added options:
         | 
| 437 | 
            -
                * :file_encoding : defaults to utf8  (thanks to MrTin, Paxa)
         | 
| 438 | 
            -
             | 
| 439 | 
            -
            #### 1.0.6 (2013-05-19)
         | 
| 440 | 
            -
             | 
| 441 | 
            -
             * bugfix : quoted fields are now correctly parsed
         | 
| 442 | 
            -
             | 
| 443 | 
            -
            #### 1.0.5 (2013-05-08)
         | 
| 444 | 
            -
             | 
| 445 | 
            -
             * bugfix : for :headers_in_file option
         | 
| 446 | 
            -
             | 
| 447 | 
            -
            #### 1.0.4 (2012-08-17)
         | 
| 448 | 
            -
             | 
| 449 | 
            -
             * renamed the following options:
         | 
| 450 | 
            -
                * :strip_whitepace_from_values => :strip_whitespace   - removes leading/trailing whitespace from headers and values
         | 
| 451 | 
            -
             | 
| 452 | 
            -
            #### 1.0.3 (2012-08-16)
         | 
| 453 | 
            -
             | 
| 454 | 
            -
             * added the following options:
         | 
| 455 | 
            -
                * :strip_whitepace_from_values   - removes leading/trailing whitespace from values
         | 
| 456 | 
            -
             | 
| 457 | 
            -
            #### 1.0.2 (2012-08-02)
         | 
| 458 | 
            -
             | 
| 459 | 
            -
             * added more options for dealing with headers:
         | 
| 460 | 
            -
                * :user_provided_headers ,user provided Array with header strings or symbols, to precisely define what the headers should be, overriding any in-file headers (default: nil)
         | 
| 461 | 
            -
                * :headers_in_file , if the file contains headers as the first line (default: true)
         | 
| 462 | 
            -
             | 
| 463 | 
            -
            #### 1.0.1 (2012-07-30)
         | 
| 464 | 
            -
             | 
| 465 | 
            -
             * added the following options:
         | 
| 466 | 
            -
                * :downcase_header
         | 
| 467 | 
            -
                * :strings_as_keys
         | 
| 468 | 
            -
                * :remove_zero_values
         | 
| 469 | 
            -
                * :remove_values_matching
         | 
| 470 | 
            -
                * :remove_empty_hashes
         | 
| 471 | 
            -
                * :convert_values_to_numeric
         | 
| 472 | 
            -
             | 
| 473 | 
            -
             * renamed the following options:
         | 
| 474 | 
            -
                * :remove_empty_fields => :remove_empty_values
         | 
| 475 | 
            -
             | 
| 476 | 
            -
             | 
| 477 | 
            -
            #### 1.0.0 (2012-07-29)
         | 
| 478 | 
            -
             | 
| 479 | 
            -
             * renamed `SmarterCSV.process_csv` to `SmarterCSV.process`.
         | 
| 480 | 
            -
             | 
| 481 | 
            -
            #### 1.0.0.pre1 (2012-07-29)
         | 
| 482 | 
            -
             | 
| 329 | 
            +
            ```
         | 
| 330 | 
            +
            ## [ChangeLog](./CHANGELOG.md)
         | 
| 483 331 |  | 
| 484 332 | 
             
            ## Reporting Bugs / Feature Requests
         | 
| 485 333 |  | 
| 486 334 | 
             
            Please [open an Issue on GitHub](https://github.com/tilo/smarter_csv/issues) if you have feedback, new feature requests, or want to report a bug. Thank you!
         | 
| 487 335 |  | 
| 336 | 
            +
              * please include a small sample CSV file
         | 
| 337 | 
            +
              * please mention your version of SmarterCSV, Ruby, Rails
         | 
| 488 338 |  | 
| 489 | 
            -
            ## Special Thanks
         | 
| 490 | 
            -
             | 
| 491 | 
            -
            Many thanks to people who have filed issues and sent comments.
         | 
| 492 | 
            -
            And a special thanks to those who contributed pull requests:
         | 
| 493 | 
            -
             | 
| 494 | 
            -
             * [Jack 0](https://github.com/xjlin0)
         | 
| 495 | 
            -
             * [Alejandro](https://github.com/agaviria)
         | 
| 496 | 
            -
             * [Lucas Camargo de Almeida](https://github.com/lcalmeida)
         | 
| 497 | 
            -
             * [Raphaël Bleuse](https://github.com/bleuse)
         | 
| 498 | 
            -
             * [feens](https://github.com/feens)
         | 
| 499 | 
            -
             * [César Camacho](https://github.com/chanko)
         | 
| 500 | 
            -
             * [innhyu](https://github.com/innhyu)
         | 
| 501 | 
            -
             * [Benjamin Thouret](https://github.com/benichu)
         | 
| 502 | 
            -
             * [Chris Hilton](https://github.com/chrismhilton)
         | 
| 503 | 
            -
             * [Sean Duckett](http://github.com/sduckett)
         | 
| 504 | 
            -
             * [Alex Ong](http://github.com/khaong)
         | 
| 505 | 
            -
             * [Martin Nilsson](http://github.com/MrTin)
         | 
| 506 | 
            -
             * [Eustáquio Rangel](http://github.com/taq)
         | 
| 507 | 
            -
             * [Pavel](http://github.com/paxa)
         | 
| 508 | 
            -
             * [Félix Bellanger](https://github.com/Keeguon)
         | 
| 509 | 
            -
             * [Graham Wetzler](https://github.com/grahamwetzler)
         | 
| 510 | 
            -
             * [Marcos G. Zimmermann](https://github.com/marcosgz)
         | 
| 511 | 
            -
             * [Jordan Running](https://github.com/jrunning)
         | 
| 512 | 
            -
             * [Dave Sanders](https://github.com/DaveSanders)
         | 
| 513 | 
            -
             * [Hugo Lepetit](https://github.com/giglemad)
         | 
| 514 | 
            -
             * [esBeee](https://github.com/esBeee)
         | 
| 515 | 
            -
             * [Waldyr de Souza](https://github.com/waldyr)
         | 
| 516 | 
            -
             * [Ben Maher](https://github.com/benmaher)
         | 
| 517 | 
            -
             * [Wal McConnell](https://github.com/wal)
         | 
| 518 | 
            -
             * [Jordan Graft](https://github.com/jordangraft)
         | 
| 519 | 
            -
             * [Michael](https://github.com/polycarpou)
         | 
| 520 | 
            -
             * [Kevin Coleman](https://github.com/KevinColemanInc)
         | 
| 521 | 
            -
             * [Tirdad C.](https://github.com/tridadc)
         | 
| 522 | 
            -
             * [Dave Myron](https://github.com/contentfree)
         | 
| 523 | 
            -
             * [Ivan Ushakov](https://github.com/IvanUshakov)
         | 
| 524 | 
            -
             * [Matthieu Paret](https://github.com/mtparet)
         | 
| 525 | 
            -
             * [Rohit Amarnath](https://github.com/ramarnat)
         | 
| 526 | 
            -
             * [Joshua Smith](https://github.com/enviable)
         | 
| 527 | 
            -
             * [Colin Petruno](https://github.com/colinpetruno)
         | 
| 528 | 
            -
             * [Diego Salido](https://github.com/salidux)
         | 
| 339 | 
            +
            ## [A Special Thanks to all Contributors!](CONTRIBUTORS.md) 🎉🎉🎉
         | 
| 529 340 |  | 
| 530 341 |  | 
| 531 342 | 
             
            ## Contributing
         | 
    
        data/Rakefile
    CHANGED
    
    | @@ -1,26 +1,19 @@ | |
| 1 1 | 
             
            #!/usr/bin/env rake
         | 
| 2 2 | 
             
            require "bundler/gem_tasks"
         | 
| 3 | 
            -
             | 
| 4 3 | 
             
            require 'rubygems'
         | 
| 5 4 | 
             
            require 'rake'
         | 
| 6 | 
            -
             | 
| 7 5 | 
             
            require 'rspec/core/rake_task'
         | 
| 8 6 |  | 
| 7 | 
            +
            task :default => :spec
         | 
| 8 | 
            +
             | 
| 9 9 | 
             
            desc "Run RSpec"
         | 
| 10 10 | 
             
            RSpec::Core::RakeTask.new do |t|
         | 
| 11 | 
            -
              t.verbose = false
         | 
| 11 | 
            +
              # t.verbose = false
         | 
| 12 12 | 
             
            end
         | 
| 13 13 |  | 
| 14 | 
            -
            desc  | 
| 15 | 
            -
            task : | 
| 16 | 
            -
               | 
| 14 | 
            +
            desc 'Run spec with coverage'
         | 
| 15 | 
            +
            task :coverage do
         | 
| 16 | 
            +
              ENV['COVERAGE'] = 'true'
         | 
| 17 | 
            +
              Rake::Task['spec'].execute
         | 
| 18 | 
            +
              `open coverage/index.html`
         | 
| 17 19 | 
             
            end
         | 
| 18 | 
            -
             | 
| 19 | 
            -
            # task :spec_all do
         | 
| 20 | 
            -
            #   %w[active_record data_mapper mongoid].each do |model_adapter|
         | 
| 21 | 
            -
            #     puts "MODEL_ADAPTER = #{model_adapter}"
         | 
| 22 | 
            -
            #     system "rake spec MODEL_ADAPTER=#{model_adapter}"
         | 
| 23 | 
            -
            #   end
         | 
| 24 | 
            -
            # end
         | 
| 25 | 
            -
             | 
| 26 | 
            -
            task :default => :spec
         |