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