class TableTransform::Table
Attributes
column_properties[RW]
formulas[RW]
table_properties[R]
Public Class Methods
create_empty(header, table_properties = {})
click to toggle source
# File lib/table_transform/table.rb, line 23 def self.create_empty(header, table_properties = {}) raise 'Table header need to be array' unless header.is_a? Array raise 'Table, No header defined' if header.empty? Table.new([header], table_properties) end
create_from_file(file_name, sep = ',')
click to toggle source
# File lib/table_transform/table.rb, line 16 def self.create_from_file(file_name, sep = ',') rows = CSV.read(file_name, { :col_sep => sep }) raise "'#{file_name}' contains no data" if rows.empty? Table.new(rows) end
new(rows, table_properties = {})
click to toggle source
@throws if column names not unique @throws if column size for each row match
# File lib/table_transform/table.rb, line 31 def initialize(rows, table_properties = {}) raise 'Table required to have at least a header row' if (rows.nil? or rows.empty?) @data_rows = rows.clone header = @data_rows.shift @column_indexes = create_column_name_binding(header) @formulas = {} @table_properties = TableProperties.new(table_properties) @column_properties = Hash.new{|_hash, key| raise "No column with name '#{key}' exists"} create_column_properties(*header,{}) validate_header_uniqueness(header) validate_column_size end
Public Instance Methods
+(table)
click to toggle source
Add two tables @throws if header or properties do not match
# File lib/table_transform/table.rb, line 73 def +(table) t2 = table.to_a t2_header = t2.shift raise 'Tables cannot be added due to header mismatch' unless @column_properties.keys == t2_header raise 'Tables cannot be added due to column properties mismatch' unless column_properties_eql? table.column_properties raise 'Tables cannot be added due to table properties mismatch' unless @table_properties.to_h == table.table_properties.to_h TableTransform::Table.new(self.to_a + t2) end
<<(hash_values)
click to toggle source
# File lib/table_transform/table.rb, line 66 def << (hash_values) @data_rows << create_row(hash_values) self end
add_column(name, column_properties = {}) { |row)| ... }
click to toggle source
adds a column with given name to the far right of the table @throws if given column name already exists
# File lib/table_transform/table.rb, line 116 def add_column(name, column_properties = {}) validate_column_absence(name) create_column_properties(name, column_properties) @data_rows.each{|x| x << (yield Row.new(@column_indexes, x)) } @column_indexes[name] = @column_indexes.size self # enable chaining end
add_column_formula(column, formula, column_properties = {})
click to toggle source
# File lib/table_transform/table.rb, line 60 def add_column_formula(column, formula, column_properties = {}) add_column(column, column_properties){nil} @formulas[column] = formula self # self chaining end
change_column(name) { |row| ... }
click to toggle source
# File lib/table_transform/table.rb, line 126 def change_column(name) raise "Column with formula('#{name}') cannot be changed" if @formulas[name] index = Util::get_col_index(name, @column_indexes) @data_rows.each{|r| r[index] = yield Row.new(@column_indexes, r) } self # enable chaining end
delete_column(*names)
click to toggle source
# File lib/table_transform/table.rb, line 136 def delete_column(*names) validate_column_exist(*names) names.each{|n| @column_properties.delete(n) @formulas.delete(n) } selected_cols = @column_indexes.values_at(*@column_properties.keys) @data_rows.map!{|row| row.values_at(*selected_cols)} @column_indexes = create_column_name_binding(@column_properties.keys) self end
each_row() { |row| ... }
click to toggle source
# File lib/table_transform/table.rb, line 82 def each_row @data_rows.each{|x| yield Row.new(@column_indexes, x) } end
extract(header)
click to toggle source
@returns new table with specified columns specified in given header
# File lib/table_transform/table.rb, line 95 def extract(header) validate_column_exist(*header) selected_cols = @column_indexes.values_at(*header) t = Table.new( @data_rows.inject([header]) {|res, row| (res << row.values_at(*selected_cols))}, @table_properties.to_h ) header.each{|h| t.column_properties[h].reset(@column_properties[h].to_h)} t.formulas = header.zip(@formulas.values_at(*header)).to_h t end
filter() { |row| ... }
click to toggle source
@returns new table with rows that match given block
# File lib/table_transform/table.rb, line 105 def filter table_prop = @table_properties.to_h col_prop = @column_properties.keys.clone t = Table.new( (@data_rows.select {|row| yield Row.new(@column_indexes, row)}.unshift col_prop), table_prop ) t.formulas = @formulas.clone t.column_properties = @column_properties.clone t end
metadata()
click to toggle source
Returns meta data as Hash with header name as key
# File lib/table_transform/table.rb, line 55 def metadata warn 'metadata is deprecated. Use column_properties[] instead' @column_properties.inject({}){|res, (k, v)| res.merge!({k => v.to_h})} end
rename_column(from, to)
click to toggle source
# File lib/table_transform/table.rb, line 150 def rename_column(from, to) validate_column_exist(from) validate_column_absence(to) @column_properties = @column_properties.map{|k,v| [k == from ? to : k, v] }.to_h @formulas = @formulas.map{|k,v| [k == from ? to : k, v] }.to_h @column_indexes = create_column_name_binding(@column_properties.keys) end
set_metadata(*columns, metadata)
click to toggle source
Sets metadata for given columns Example:
set_metadata('Col1', {format: '#,##0'})
# File lib/table_transform/table.rb, line 49 def set_metadata(*columns, metadata) warn 'set_metadata is deprecated. Use column_properties[] instead' columns.each{|c| @column_properties[c].reset(metadata)} end
to_a()
click to toggle source
@returns array of data arrays including header row
# File lib/table_transform/table.rb, line 89 def to_a res = @data_rows.clone res.unshift @column_properties.keys.clone end
Private Instance Methods
column_properties_eql?(column_properties)
click to toggle source
# File lib/table_transform/table.rb, line 235 def column_properties_eql?(column_properties) return false unless @column_properties.size == column_properties.size @column_properties.each{|key, prop| return false unless prop.to_h == column_properties[key].to_h} end
create_column_name_binding(header_row)
click to toggle source
# File lib/table_transform/table.rb, line 223 def create_column_name_binding(header_row) header_row.map.with_index{ |x, i| [x, i] }.to_h end
create_column_properties(*header, properties)
click to toggle source
# File lib/table_transform/table.rb, line 231 def create_column_properties(*header, properties) header.each{|key| @column_properties.store(key, TableTransform::Table::ColumnProperties.new(properties))} end
create_row(hash_values)
click to toggle source
# File lib/table_transform/table.rb, line 227 def create_row(hash_values) @column_properties.keys.inject([]) { |row, col| row << hash_values.fetch(col){raise "Value for column '#{col}' could not be found"} } end
validate_column_absence(name)
click to toggle source
# File lib/table_transform/table.rb, line 256 def validate_column_absence(name) raise "Column '#{name}' already exists" if @column_properties.keys.include?(name) end
validate_column_exist(*names)
click to toggle source
# File lib/table_transform/table.rb, line 251 def validate_column_exist(*names) diff = names - @column_properties.keys raise raise "No column with name '#{diff.first}' exists" if diff.size > 0 end
validate_column_size()
click to toggle source
@throws unless all rows have same number of elements
# File lib/table_transform/table.rb, line 247 def validate_column_size @data_rows.each_with_index {|x, index| raise "Column size mismatch. On row #{index+1}. Size #{x.size} expected to be #{@column_properties.size}" if @column_properties.size != x.size} end
validate_header_uniqueness(header)
click to toggle source
@throws unless all header names are unique
# File lib/table_transform/table.rb, line 241 def validate_header_uniqueness(header) dup = header.select{ |e| header.count(e) > 1 }.uniq raise "Column(s) not unique: #{dup.map{|x| "'#{x}'"}.join(', ')}" if dup.size > 0 end