Posted 5 days ago. Visible to the public.

Ruby: Reading and writing CSVs

In ruby you can easily read and write CSVs with the standard CSV library class.

On top of this, you can use the gem smarter_csv for reading (not writing) CSVs in a more comfortable way:

  • Keep in mind, that the development of this gem is in an unknown state and the 2.0 release seems to happen never
  • The API will change completely for 2.0, so you might find a bunch of unrelated documentation for 1.2
  • It allows you to read in chunks (relevant for large CSVs)

Here is an example, what smarter_csv does for you:

Input:

Copy
first name,last name,dogs,cats,birds,fish Dan,McAllister,2,,, Lucy,Laweless,,5,, Miles,O'Brian,,,,21 Nancy,Homes,2,,1,

Output:

Copy
[ {first_name: 'Dan', last_name: 'McAllister', dogs: '2'}, {first_name: 'Lucy', last_name: 'Laweless', cats: '5'}, {first_name: 'Miles', last_name: "O'Brian", fish: '21'}, {first_name: 'Nancy', last_name: 'Homes', dogs: '2', birds: '1'} ]

You might want to keep empty lines, use string keys or change the encoding. This is all possible, look up for the proper options.

RSpec

We used this helper in some project to do not have to write comma separated values, but use data objects instead.

Place this file in spec/supper/csv_helper.rb.

Copy
module CsvHelpers def generate_csv(csv_data) csv_string = CSV.generate do |csv| csv << csv_data.first.keys csv_data.inject(csv) { |acc, row| acc << row.values } end file = Tempfile.new file.write(csv_string) file.rewind file end def generate_empty_csv file = Tempfile.new file.write(' ') file.rewind file end end RSpec.configure do |c| c.include CsvHelpers end

The you can generate a csv file like this:

Copy
let(:csv_data) do [ { 'first_name' => 'Dan', 'last_name' => 'McAllister', 'dogs' => '2', 'cats' => nil, 'fish' => nil, 'birds' => nil }, { 'first_name' => 'Lucy', 'last_name' => 'Laweless', 'dogs' => nil, 'cats' => '5', 'fish' => nil, 'birds' => nil }, { 'first_name' => 'Miles', 'last_name' => "O'Brian", 'dogs' => nil, 'cats' => nil, 'fish' => '21', 'birds' => nil }, { 'first_name' => 'Nancy', 'last_name' => 'Homes', 'dogs' => '2', 'cats' => nil, 'fish' => nil, 'birds' => '1' } ] end let(:csv) { generate_csv(csv_data) } # This will return a CSV with one header row and four data rows

By refactoring problematic code and creating automated tests, makandra can vastly improve the maintainability of your Rails application.

Owner of this card:

Avatar
Emanuel De
Last edit:
5 days ago
by Emanuel De
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Emanuel De to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more