1.修改前面的CSV应用程序,使它可以用 each 方法返回 CsvRow 对象。然后,在 CsvRow 对象上, 对某个给定标题,用 method_missing 方法返回标题所在列的值。

比如,对于包含以下内容的文件:

one, two
lions, tigers

API可以像下面这样操作:

csv = RubyCsv.new
csv.each {|row| puts row.one}

这会打印出 “lions” 。

方案:

txt:

/pro/rubycsv.txt

one, two
lions, tigers
dogs, cats

code:

module ActsAsCsv
    def self.included(base)
        base.extend ClassMethods
    end
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(', ')
            @rows.push(CsvRow.new(headers,row.chomp.split(', ')))
        end
    end

    attr_accessor :headers, :csv_contents, :rows

    def initialize
        @rows = []
        read
    end

    def each
        for row in rows do
            yield row
        end
    end

    class CsvRow
        attr_accessor :headers, :row
        def initialize(headers, row)
            @headers = headers
            @row = row
        end
        def method_missing(name)
            @row[headers.index(name.to_s)]
        end
        def row
            @row
        end
    end
end

class RubyCsv
    include ActsAsCsv
    acts_as_csv
end

m = RubyCsv.new
p m.headers
p m.csv_contents
m.each {|row| puts row.one}