On Thu, May 5, 2011 at 4:19 PM, Jolyon R. <jolyonruss / gmail.com> wrote:
> I think I was averse to creating multiple classes in one file, so
> thought it best to try and create the CsvRow inline, it had crossed my
> mind but I got hung up on the semantics of the book asking for an
> object.
>
> I create a CsvRow class and am now getting an each to return a CsvRow,
> AWESOME!
>
> The next bit I'm getting a little caught up on is how to get CsvRow to
> return a single value in a row based on a headers value.
>
> When I store a line in my CsvRow like this:
>
> @fields =3D line.chomp.split(', ')
>
> Is that an array or hash?

You can read about String#split in the documentation and you will see
that it returns an array.

>
> Using method_missing and it's an array will this work:
>
> class CsvRow
> =A0attr_reader :fields, :headersPattern

Convention in Ruby is snake_case, so headers_pattern is more typical.

> =A0def initialize(line)
> =A0 =A0@fields =3D line.chomp.split(', ')
> =A0end
>
> =A0def headerPattern( pattern )
> =A0 =A0@headersPattern =3D pattern
> =A0end

Who is calling this method? If you use attr_accessor instead of
reader, you get a method called header_pattern=3D, which sets the value,
as you are doing, so that would be more convenient. Also, you are
rewriting the method headerPattern created by attr_reader with this
one. So, remove it and use attr_accessor :header_pattern.

> =A0def self.method_missing name, *args
> =A0 =A0 / headersPattern.each_with_index |header, index|
> =A0 =A0 =A0if header =3D name.to_s yield @fields.send(@headers[index])
> =A0 =A0end
> =A0end
> end

method_missing is an instance method, so drop the self there.  And I
think that you want to access the corresponding field of the header in
the @fields array, so no need to send anything, just:

def method_missing name, *args
  @header_pattern.each_with_index do |header, index|
    if header =3D=3D name.to_s
      @fields[index]
      break
    end
end

Which could be also written as:

def method_missing name, *args
  if index =3D @header_pattern.index name
    @fields[index]
  end
end

Which will find the name in the header_pattern, if it finds it indexes
the @fields array at that index. Anyway, if the numbers of headers
could be big, or the number of times you are going to call this method
is relevant, I would think of having a different data structure. I
would have a hash whose keys are the header names, and whose values
are what you have in @fields. If possible, I would pass the headers
when you construct the CsvRow, I think it's cleaner:

class CsvRow
  attr_reader :header_pattern, :values


end


>
> Thanks again for your help, it really makes a difference knowing a
> language has a community of helpful people behind it :)
>
> --
> Posted via http://www.ruby-forum.com/.
>
>