On Wed, May 4, 2011 at 9:34 AM, Jolyon R. <jolyonruss / gmail.com> wrote:
> Hey guys,
>
> I'm day 3 into The Pragmatic Programmers - Seven Languages in Seven
> Days, having previously done a little ruby. I'm from an Actionscript
> background and finding Ruby a little challenging, so bear with me.
>
> I've been parsing some very simple CSV, I've seen there are libraries
> out there to handle this, but the book is about learning.
>
> The book gives us some simple code and the task is to elaborate on it:
>
> module ActsAsCsv
>
> def self.included(base)
>  base.extend ClassMethods
> end
>
> module ClassMethods
>  def acts_as_csv
>   include InstanceMethods
>  end
> end
>
> module InstanceMethods
>
>  def read
>   @csv_contents = []
>   filename = self.class.to_s.downcase + '.txt'
>   file = File.new(filename)
>   @headers = file.gets.chomp.split(', ')
>
>   file.each do |row|
>    @csv_contents << row.chomp.split(', ')
>   end
>  end
>
>  attr_accessor :headers, :csv_contents
>
>  def initialize
>   read
>  end
>
> end
>
> end
>
> class RubyCsv # no inheritance! You can mix it in
> include ActsAsCsv
> acts_as_csv
> end
>
> m = RubyCsv.new
> puts m.headers.inspect
> puts m.csv_contents.inspect
>
> The task is to create an *each* method and return a CsvRow object
> instead of an array.
>
> So I figure I need to create the object first in the file.each loop
>
> This mess is where I got to:
>
> file.each do |row|
>    @headers.each_with_index do |head, index|
>     require 'ostruct'
>     rowObject = OpenStruct.new
>     rowObject.#{@headers[index]} = row.chomp.split(', ')
>
>    end
>    @csv_contents << rowObject
>   end
>
> But as you can see it's a mess


I think that (looking at the Day 3 self-study in the book), your best
approach will be not to modify any of the "prewritten" methods that
you are given:

define your CsvRow class first, and make it so that it is something
you can populate with the @headers array in ActsAsCsv and one item
(row) from @csv_contents. (Pay attention, here, to the book's call to
use method_missing!)

Then in your new ActsAsCsv#each method, you just need to iterate over
the @csv_contents collection, creating and yielding CsvRow objects.

I think that's the simplest route to do what you are looking for, and
once you've done that bit you can explore variations. You don't need
to use OpenStruct (or Struct) -- you could do it with them, but you'll
miss out on what the book is getting at with the call to use
method_missing.