Jolyon R. wrote in post #996621:
> 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.
>

Then I wouldn't worry too much about Jess Gabriel y Galn's code because it contains some advanced stuff.

>
> 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.
>

Typically, you call an each() method like this:

obj.each do |x|
  puts x
end

That syntax uses what's called a 'block', which is this part:

do |x|
  puts x
end

The block tells the each() method to iterate over the elements of obj, and send them to the block one by one.  The element will get assigned to the parameter variable x of the block.  In order for the each() method to send elements to the block, each() must call the yield() function. Here is an example:

class Dog
  def each
    yield 'dog'
    yield 20
    yield 'last one'
  end
end

d = Dog.new

d.each do |x|
  puts x
end

--output:--
dog
20
last one

In your case, you will be iterating over the lines of a file.  To me it seems like you need to organize your code along these lines:


class RubyCsv  # no inheritance! You can mix it in
  include ActsAsCsv

  def initialize(fname)
    @file = File.new(fname)
  end

  def each
    yield RowObject.new(@file.gets)
  end

end

class RowObject
  attr_reader :fields

  def initialize(line)
    @fields = line.chomp.split(', ')
  end
end

Note that initialize() opens the file, so somewhere you will need to close the file.