The following is my Ruby attempt at a (very) basic CSV file parser class, inspired by an exercise from the book Seven Languages in Seven Weeks. I'm a Ruby novice and will be grateful for any suggestions for improvement.
#!/usr/local/bin/ruby -w # CSV file parser. # # USAGE: # CsvFile.new('data.csv').each { |row| puts row.firstname } # class CsvFile # Parses the given CSV file into a collection of rows. # def initialize file @rows = [] headers = file.gets.chomp.split(", ") file.each do |line| values = {} headers.zip(line.chomp.split(", ")).each do |key, value| values[key] = value end @rows << CsvRow.new(values) end end # Iterates over all rows. # def each @rows.each { |row| yield(row) } end # Returns the index-th row, or null if no such row exists. # def [] index @rows[index] end end # CSV row. # class CsvRow # Creates a new CSV row with the given values. # # * *Args* : # - +values+ -> a hash containing the column -> value mapping # def initialize values @values = values end # Returns the value in the column given as method name, or null if # no such value exists. # def method_missing name, *args @values[name.to_s] end end # TEST CASES # class AssertionError < RuntimeError end def assert &block raise AssertionError unless yield end require 'stringio' file = StringIO.new( "firstname, lastname, age, sex Andrej, Beles, 25, male Delia, Marin, 20, female Henry, Prahanth, 33, male" ) csvFile = CsvFile.new(file) row = csvFile[0] assert { row.firstname == "Andrej" } assert { row.lastname == "Beles" } assert { row.age == "25" } assert { row.sex == "male" } row = csvFile[1] assert { row.firstname == "Delia" } assert { row.lastname == "Marin" } assert { row.age == "20" } assert { row.sex == "female" } row = csvFile[2] assert { row.firstname == "Henry" } assert { row.lastname == "Prahanth" } assert { row.age == "33" } assert { row.sex == "male" } puts "DONE."