module ETL #:nodoc: module Parser #:nodoc: # Parser for fixed with files class FixedWidthParser < ETL::Parser::Parser include Enumerable # Initialize the parser # * source: The source object def initialize(source) super configure end # Return each row def each Dir.glob(file).each do |file| open(file).each do |line| row = {} fields.each do |name, f| # TODO make strip optional? row[name] = convert(name, line[f.field_start, f.field_length].strip, f.type) end yield row end end end # Return a map of defined fields def fields @fields ||= {} end private def configure source.definition.each do |field, options| fields[field] = FixedWidthField.new(options[:name], options[:start], options[:end], options[:length], options[:type]) end end end class FixedWidthField attr_reader :name, :field_start, :field_end, :field_length, :type def initialize(name, field_start, field_end=nil, field_length=nil, type=nil) @name = name @type = type ||= :string @field_start = field_start - 1 if field_end @field_end = field_end @field_length = @field_end - @field_start elsif field_length @field_length = field_length @field_end = @field_start + @field_length else raise DefinitionError, "Either field_end or field_length required" end end end end end