loading
main.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# Create a child class of Array called CsvRow that allows access by key
# Any unknown method name is interpreted as a key
# This could probably be refactored into a hash, but I wanted to show the power of method_missing!
class CsvRow < Array
  def initialize(data, headers)
    super(data)
    @headers = headers
  end   
  attr_accessor :headers
  def method_missing name, *args
    column_name = name.to_s
    return self[headers.find_index(column_name)]
  end
end

# We use can apply this mixing by including ActsAsCsv and invoking acts_as_csv
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 + '.csv'
      file = File.new(filename)
      @headers = file.gets.chomp.split(', ')

      file.each do |row|
        @csv_contents << CsvRow.new(row.chomp.split(', '), headers)
      end
    end

    attr_accessor :headers, :csv_contents
    def initialize
      read
    end

    def each(&block)
      @csv_contents.each(&block) 
      self
    end

    def self.method_missing name, *args
      column_name = name.to_s
    end
  end
end

# Now we apply our cool mixin to an arbitrary pop culture reference
class KingsOfWesteros
  include ActsAsCsv
  acts_as_csv
end
kings_of_westeros = KingsOfWesteros.new
puts "Behold the Kings of Westeros"
kings_of_westeros.each do |king|
  puts "#{king.name}#{king.nickname != "" ? " called " + king.nickname : ""} ruled Westeros from #{king.start} to #{king.end}"
end
puts "👑🙇‍♂️"
ruby 2.5.5p157 (2019-03-15 revision 67260) [x86_64-linux]