class HoneyFormat::Header

Represents a header

Public Class Methods

new( header, converter: HoneyFormat.header_converter, deduplicator: HoneyFormat.config.header_deduplicator ) click to toggle source

Instantiate a Header @return [Header] a new instance of Header. @param [Array<String>] header array of strings. @param converter [#call, Symbol, Hash]

header converter that implements a #call method
that takes one column (string) argument OR symbol for a registered
converter registry OR a hash mapped to a symbol or something that responds
to #call.

@param deduplicator [#call, Symbol]

header deduplicator that implements a #call method
that takes columns Array<String> argument OR symbol for a registered
deduplicator registry.

@raise [HeaderError] super class of errors raised when there is a CSV header error. @raise [MissingHeaderColumnError] raised when header is missing @example Instantiate a header with a custom converter

converter = ->(col) { col == 'username' ? 'handle' : col }
header = HoneyFormat::Header.new(['name', 'username'], converter: converter)
header.to_a # => ['name', 'handle']
# File lib/honey_format/matrix/header.rb, line 28
def initialize(
  header,
  converter: HoneyFormat.header_converter,
  deduplicator: HoneyFormat.config.header_deduplicator
)
  if header.nil? || header.empty?
    raise(Errors::MissingHeaderError, "CSV header can't be empty.")
  end

  @original_header = header
  self.deduplicator = deduplicator
  self.converter = converter
  @columns = build_columns(@original_header)
end

Public Instance Methods

columns() click to toggle source

Returns columns as array. @return [Array<Symbol>] of columns.

# File lib/honey_format/matrix/header.rb, line 65
def columns
  @columns
end
each(&block) click to toggle source

@yield [row] The given block will be passed for every column. @yieldparam [Row] a column in the CSV header. @return [Enumerator]

If no block is given, an enumerator object will be returned.
# File lib/honey_format/matrix/header.rb, line 59
def each(&block)
  columns.each(&block)
end
empty?() click to toggle source

Returns true if columns contains no elements. @return [true, false] true if columns contains no elements.

# File lib/honey_format/matrix/header.rb, line 51
def empty?
  @columns.empty?
end
length() click to toggle source

Return the number of header columns @return [Integer] the number of header columns

# File lib/honey_format/matrix/header.rb, line 77
def length
  columns.length
end
Also aliased as: size
original() click to toggle source

Returns the original header @return [Array<String>] the original header

# File lib/honey_format/matrix/header.rb, line 45
def original
  @original_header
end
size()
Alias for: length
to_a() click to toggle source

Returns columns as array. @return [Array<Symbol>] of columns.

# File lib/honey_format/matrix/header.rb, line 71
def to_a
  columns
end
to_csv(columns: nil) click to toggle source

Header as CSV-string @return [String] CSV-string representation.

# File lib/honey_format/matrix/header.rb, line 84
def to_csv(columns: nil)
  attributes = if columns
                 self.columns & columns.map(&:to_sym)
               else
                 self.columns
               end

  ::CSV.generate_line(attributes)
end

Private Instance Methods

build_columns(header) click to toggle source

Convert original header @param [Array<String>] header the original header @return [Array<String>] converted columns

# File lib/honey_format/matrix/header.rb, line 128
def build_columns(header)
  columns = header.each_with_index.map do |header_column, index|
    convert_column(header_column, index).tap do |column|
      maybe_raise_missing_column!(column)
    end
  end

  @deduplicator.call(columns)
end
call_column_builder(callable, value, index) click to toggle source
# File lib/honey_format/matrix/header.rb, line 188
def call_column_builder(callable, value, index)
  return callable.call if callable_arity(callable).zero?
  return callable.call(value) if callable_arity(callable) == 1
  callable.call(value, index)
end
callable_arity(callable) click to toggle source

Returns the callable object method arity @param [#arity, call] callable thing that responds to call and maybe arity @return [Integer] the method arity

# File lib/honey_format/matrix/header.rb, line 149
def callable_arity(callable)
  # procs and lambdas respond to #arity
  return callable.arity if callable.respond_to?(:arity)

  callable.method(:call).arity
end
convert_column(column, index) click to toggle source

Convert the column value @param [String, Symbol] column the CSV header column value @param [Integer] index the CSV header column index @return [Symbol] the converted column

# File lib/honey_format/matrix/header.rb, line 142
def convert_column(column, index)
  call_column_builder(@converter, column, index)&.to_sym
end
converter=(object) click to toggle source

Set the header converter @param [Hash, Symbol, call] symbol to known converter, object that responds to call or Hash @return [nil]

# File lib/honey_format/matrix/header.rb, line 99
def converter=(object)
  if object.is_a?(Symbol)
    @converter = HoneyFormat.converter_registry[object]
    return
  end

  if object.is_a?(Hash)
    @converter = hash_converter(object)
    return
  end

  @converter = object
end
deduplicator=(object) click to toggle source

Set the header deduplicator @param [Symbol, call] symbol to known deduplicator or object that responds to call @return [nil]

# File lib/honey_format/matrix/header.rb, line 116
def deduplicator=(object)
  if object.is_a?(Symbol)
    @deduplicator = HoneyFormat.header_deduplicator_registry[object]
    return
  end

  @deduplicator = object
end
hash_converter(hash) click to toggle source
# File lib/honey_format/matrix/header.rb, line 170
def hash_converter(hash)
  lambda { |value, index|
    # support strings and symbol keys interchangeably
    column = hash.fetch(value) do
      key = value.respond_to?(:to_sym) ? value.to_sym : value
      # if column is unmapped use the default header converter
      hash.fetch(key) { HoneyFormat.header_converter.call(value, index) }
    end

    # The hash can contain mixed values, Symbol and procs
    if column.respond_to?(:call)
      column = call_column_builder(column, value, index)
    end

    column&.to_sym
  }
end
maybe_raise_missing_column!(column) click to toggle source

Raises an error if header column is missing/empty @param [Object] column the CSV header column @raise [Errors::MissingHeaderColumnError]

# File lib/honey_format/matrix/header.rb, line 159
def maybe_raise_missing_column!(column)
  return if column && !column.empty?

  parts = [
    "CSV header column can't be nil or empty!",
    'When you pass your own converter make sure that it never returns nil or an empty string.', # rubocop:disable Metrics/LineLength
    'Instead generate unique columns names.',
  ]
  raise(Errors::MissingHeaderColumnError, parts.join(' '))
end