lib/chronicle/etl/loaders/table_loader.rb in chronicle-etl-0.2.4 vs lib/chronicle/etl/loaders/table_loader.rb in chronicle-etl-0.3.0
- old
+ new
@@ -1,22 +1,72 @@
require 'tty/table'
+require 'active_support/core_ext/string/filters'
+require 'active_support/core_ext/hash/reverse_merge'
module Chronicle
module ETL
class TableLoader < Chronicle::ETL::Loader
- def initialize(options)
- super(options)
+ register_connector do |r|
+ r.description = 'an ASCII table'
end
+ DEFAULT_OPTIONS = {
+ fields_limit: nil,
+ fields_exclude: ['lids', 'type'],
+ fields_include: [],
+ truncate_values_at: nil,
+ table_renderer: :basic
+ }.freeze
+
+ def initialize(options={})
+ @options = options.reverse_merge(DEFAULT_OPTIONS)
+ @records = []
+ end
+
def load(record)
- record_hash = record.to_h_flattened
- @table ||= TTY::Table.new(header: record_hash.keys)
- values = record_hash.values.map{|x| x.to_s[0..30]}
- @table << values
+ @records << record.to_h_flattened
end
def finish
- puts @table.render(:ascii, padding: [0, 1]) if @table
+ return if @records.empty?
+
+ headers = build_headers(@records)
+ rows = build_rows(@records, headers)
+
+ @table = TTY::Table.new(header: headers, rows: rows)
+ puts @table.render(
+ @options[:table_renderer].to_sym,
+ padding: [0, 2, 0, 0]
+ )
+ end
+
+ private
+
+ def build_headers(records)
+ headers =
+ if @options[:fields_include].any?
+ Set[*@options[:fields_include]]
+ else
+ # use all the keys of the flattened record hash
+ Set[*records.map(&:keys).flatten.map(&:to_s).uniq]
+ end
+
+ headers = headers.delete_if { |header| header.end_with?(*@options[:fields_exclude]) } if @options[:fields_exclude].any?
+ headers = headers.first(@options[:fields_limit]) if @options[:fields_limit]
+
+ headers.to_a.map(&:to_sym)
+ end
+
+ def build_rows(records, headers)
+ records.map do |record|
+ values = record.values_at(*headers).map{|value| value.to_s }
+
+ if @options[:truncate_values_at]
+ values = values.map{ |value| value.truncate(@options[:truncate_values_at]) }
+ end
+
+ values
+ end
end
end
end
end