class CsvHuman::Columns

Public Class Methods

build( values, header_converter ) click to toggle source
# File lib/csvhuman/column.rb, line 10
def self.build( values, header_converter )

  ## "clean" unify/normalize names
  keys = values.map do |value|
    if value
      if value.empty?
        nil
      else
        ## e.g. #ADM1 CODE                      => #adm1 +code
        ##      POPULATION F CHILDREN AFFECTED  => #population +affected +children +f
        tag_key = Tag.normalize( value )
        ## turn empty normalized tags (e.g. "stray" hashtag) into nil too

        if value.empty?
            nil
        else
            header_key =
            ##   todo/fix: pass in column index - why? why not?
            ##     pass in column index for all columns (or only tagged ones?) or both?
            ##   if header_converter.arity == 1  # straight converter
                   header_converter.call( tag_key )
            ##   else
            ##       header_converter.call( value, index )
            ##    end

            ## note:
            ##   return nil, "" or false to skip column
            if header_key.nil? || header_key.empty? || header_key == false   ## check again: skip empty "" columns
              nil
            else
              ##  note: return header_key (used for returned record/hash) AND tag_key (used for type conversion config)
              ## lets us fold more columns into one or splat single list/array columns into many
              [header_key,tag_key]
            end
        end
      end
    else  # keep (nil) as is
      nil
    end
  end


  counts = {}
  keys.each_with_index do |key,i|
     if key
       header_key = key[0]
       counts[header_key] ||= []
       counts[header_key] << i
     end
  end
  ## puts "counts:"
  ## pp counts


  ## create all unique tags  (used for type conversion)
  tags = {}
  keys.each do |key|
    if key
      tag_key = key[1]
      tags[tag_key] ||= Tag.parse( tag_key )  ## note: "reuse" tag for all columns if same tag key
    end
  end
  ## puts "tags:"
  ## pp tags


  cols = []
  keys.each do |key|
    if key
      header_key = key[0]
      tag_key    = key[1]

      count = counts[header_key]
      tag   = tags[tag_key]        ## note: "reuse" tag for all columns if same tag key

      if count.size > 1
        ## note: defaults to use "standard/default" tag key (as a string)
        cols << Column.new( header_key, tag, list: true )
      else
        cols << Column.new( header_key, tag )
      end
    else
      cols << Column.new
    end
  end

  cols
end