Sorry, pressed wrong key...

2011/5/5 Jes=FAs Gabriel y Gal=E1n <jgabrielygalan / gmail.com>:
> 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. =A0And 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
> =A0 / header_pattern.each_with_index do |header, index|
> =A0 =A0if header =3D=3D name.to_s
> =A0 =A0 =A0@fields[index]
> =A0 =A0 =A0break
> =A0 =A0end
> end
>
> Which could be also written as:
>
> def method_missing name, *args
> =A0if index =3D @header_pattern.index name
> =A0 =A0@fields[index]
> =A0end
> 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

  def initialize headers, line
    @header_pattern =3D headers
    @values =3D line.chomp.split(",")
    @hash =3D Hash[*@header_pattern.zip(@values).flatten]
  end

  def method_missing name, *args
    @hash[name]
  end
end

Hope this helps,

Jesus.