Sha256: 6587c8de088eede1e4a97d10bf7184996f5a4438b51a2690c5f9f54fe0d0bcd7

Contents?: true

Size: 1.7 KB

Versions: 1

Compression:

Stored size: 1.7 KB

Contents

# frozen_string_literal: true

require 'time'

module ArrayHasher
  class Formatter
    attr_accessor :cols, :types

    REGEXP_EMPTY = /\A\s*\z/

    TYPES = {
      int: Proc.new { |v| (v.nil? || v =~ REGEXP_EMPTY) ? nil : v.gsub(/[^\d]+/, '').to_i },
      float: Proc.new { |v| (v.nil? || v =~ REGEXP_EMPTY) ? nil : v.gsub(/[^\d\.]+/, '').to_f },
      string: Proc.new { |v| v.to_s },
      time: Proc.new { |v| v ? Time.parse(v) : nil },
      json: Proc.new { |v| v ? JSON.parse(v) : nil },
      date: Proc.new { |v| v ? Date.parse(v) : nil }
    }

    # cols:
    #   [
    #     [], # ignore this col
    #     [:name, :string],
    #     [:amount, :int],
    #     [:type], # don't change val
    #     [:other, Proc {|v| v.to_i % 2}]  # convert val by proc
    #     [:all, nil, range: 0..-1]
    #   ]
    def initialize(cols)
      @types = TYPES.clone

      @cols = cols.map do |name, type, opts|
        [
          name ? name.to_sym : nil,
          (type.nil? || type.is_a?(Proc)) ? type : type.to_sym,
          (opts || {}).each_with_object({}) { |kv, r| r[kv[0].to_sym] = kv[1] }
        ]
      end
    end

    def define_type(type, &block)
      types[type.to_sym] = block
    end

    def parse(arr)
      cols.each_with_index.each_with_object({}) do |col_and_index, result|
        col_opts, index = col_and_index
        name, type, opts = col_opts
        opts ||= {}
        next if name.nil?

        range = opts[:range] || index
        val = range.is_a?(Array) ? arr.slice(*range) : arr[range]

        result[name] = if type.is_a?(Proc)
          type.call(val)
        elsif type && (block = types[type.to_sym])
          block.call(val)
        else
          val
        end
      end
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
array_hasher-0.1.5 lib/array_hasher/formatter.rb