require 'chain_flow'

class TimeEntry < Struct.new(:options)
  def to_s
    puts "employee_id: #{options[:employee_id]}"
    puts "office: #{options[:office]}"
    puts "last_name: #{options[:last_name]}"
  end
end

module Parser
  extend self

  # parse1 method from Pat Shaughnessy article
  # http://patshaughnessy.net/2014/4/8/using-a-ruby-class-to-write-functional-code
  def parse(lines)
    lines.each do |line|
      name, employee_id, office = line.split(',')
      puts "employee_id: #{employee_id}"
      puts "office: #{office}"

      last_name, first_name = name.split
      puts "last_name: #{last_name}"
    end
  end
end

module ChainFlowParser
  include ChainFlow
  extend self

  def parse(lines)
    # using Enumerator::Lazy to avoid memory bloating
    flow(lines.lazy) do
      parse_values
      build_objects
      output
    end.force
  end

  private

  def parse_values(lines)
    lines.map do |line|
      line.split(',')
    end
  end

  def build_objects(values_data)
    values_data.map do |values|
      TimeEntry.new(
        last_name: values[0].split[1],
        employee_id: values[1],
        office: values[2]
      )
    end
  end

  def output(objects)
    objects.map(&:to_s)
  end
end

data = DATA.read.lines

Parser.parse(data)
ChainFlowParser.parse(data)

__END__
Pat Shaughnessy, 23412, Boston, 3/31 8 7 7 3 0 0
Pat Shaughnessy, 23412, Boston, 3/31 1 7 1 3 0 0
Pat Shaughnessy, 23412, Boston, 3/31 8 7 9 3 0 0
Pat Shaughnessy, 23412, Boston, 3/31 8 5 7 3 0 0
Pat Shaughnessy, 23412, Boston, 3/31 9 7 7 3 1 0