Reading from a CSV File

So far our program has all the email data hardcoded: All the data is baked right into our code. Everytime you run it, it will display all the same emails. Obviously that’s not a very useful for a real world program.

Let’s change this to read our data from an external data source instead.

One very simple and pretty popular way to store data to files is using the format CSV. This stands for “comma separated values” (although, often times semicolons are used as a separator instead of commas), and it is something that spreadsheets can read and export. Being able to work with CSV can be pretty handy: just write a little Ruby script, and filter that data, or work with it otherwise.

The first line in the code below require "csv" makes Ruby’s CSV library available to your program so that you can then use the class CSV.

Exercise 15.1

Building on the same code from the last exercises, your objective is to read the email data from a file emails.csv. This file should be stored in the same directory as your Ruby program, and contain the following data:

Date,From,Subject
2014-12-01,Ferdous,Homework this week
2014-12-01,Dajana,Keep on coding! :)
2014-12-02,Ariane,Re: Homework this week
2014-12-11,Maria,I'm back in Berlin

You can create that file by copying the four lines from above to your editor.

In order to complete this exercise you’ll need to find out how to:

In other words, you should replace the following lines of code:

emails = [
  Email.new("Homework this week", { :from => "Ferdous", :date => "2014-12-01" }),
  Email.new("Keep on coding! :)", { :from => "Dajana", :date => "2014-12-01" }),
  Email.new("Re: Homework this week", { :from => "Ariane", :date => "2014-12-02" })
]

Once you have figured out how to read and parse the CSV file, and create an array of Email instances out of that data, your next task is to encapsulate all of that into a class EmailsCsvStore. This class should take a filename, and have a method read, which returns the emails array.

In the end that part of the code should read:

require "csv"

class Email
  # your class from the last exercise
end

class Mailbox
  # your class from the last exercise
end

class MailboxHtmlFormatter
  # your class from the last exercise
end

class EmailsCsvStore
  def initialize(filename)
    # fill in this method
  end

  def read
    # fill in this method
  end
end

store = EmailsCsvStore.new('emails.csv')
emails = store.read
mailbox = Mailbox.new("Ruby Study Group", emails)
formatter = MailboxHtmlFormatter.new(mailbox)

# your code from the last exercise, writing the file

Show solution