Class: Rubypivot::Pivot

Inherits:
Object
  • Object
show all
Defined in:
lib/rubypivot/pivot.rb

Overview

2020-12-30 Build an hash instead array

Constant Summary collapse

DEFAULT_OPTIONS =
{
  data_type: :integer, # :integer, :float or :string
  column_sort: true,
  row_sort: true,
  header: true,
  row_header: true,
  # column_lookup: HashName
  # row_lookup: HashName
  # row_total: 'Title for total column, if nil row total not calculated'
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source_data, column_name, row_name, value_name, options = {}) ⇒ Pivot

Returns a new instance of Pivot.

Raises:



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/rubypivot/pivot.rb', line 19

def initialize(source_data, column_name, row_name, value_name, options = {})
  @options = DEFAULT_OPTIONS.dup
  @options.merge! options if options
  raise PivotError, "Source Data must be an array of [hash|dataset]." if !source_data.is_a?(Array)
  raise PivotError, "Column name must be specified." if column_name.nil?
  raise PivotError, "Row name must be specified." if row_name.nil?
  raise PivotError, "Value name must be specified." if value_name.nil?
  # TODO: error checks for options
  @column_name = column_name.to_sym
  @row_name = row_name.to_sym
  @value_name = value_name.to_sym
  @source_data = source_data
  #
  @rows_parsed = nil # holds hash of DataRow instances
  @column_titles = nil # array of column titles
  @row_titles = nil # array of row titles
end

Instance Attribute Details

#optionsObject

Returns the value of attribute options.



18
19
20
# File 'lib/rubypivot/pivot.rb', line 18

def options
  @options
end

Class Method Details

.build(data, column_name, row_name, data_name, options = {}) ⇒ Object



166
167
168
169
# File 'lib/rubypivot/pivot.rb', line 166

def self.build(data, column_name, row_name, data_name, options = {})
  obj = self.new(data, column_name, row_name, data_name, options)
  obj.build
end

.get_title(name, line) ⇒ Object

get column title or row title



148
149
150
151
152
153
154
155
156
# File 'lib/rubypivot/pivot.rb', line 148

def self.get_title(name, line)
  if line.is_a?(Hash)
    res = line[name]
  else
    res = line.send(name)
  end
  res = 'Empty' if res.nil?
  res
end

.get_value(name, line) ⇒ Object



158
159
160
161
162
163
164
# File 'lib/rubypivot/pivot.rb', line 158

def self.get_value(name, line)
  if line.is_a?(Hash)
    line[name]
  else
    line.send(name)
  end
end

Instance Method Details

#buildObject

return an pivot array with titles



108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/rubypivot/pivot.rb', line 108

def build
  parse_data unless @rows_parsed
  res = []
  res << header_row if @options[:header]
  @row_titles.each do |row_title|
    row = @rows_parsed.get_row(row_title)
    data_array = []
    data_array << column_head(row_title) if @options[:row_header] 
    data_array += row.to_a(column_titles)
    data_array << row.total(column_titles) if @options[:row_total]
    res << data_array
  end
  res
end

#build_arrayObject

return an pivot array with titles



122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/rubypivot/pivot.rb', line 122

def build
  parse_data unless @rows_parsed
  res = []
  res << header_row if @options[:header]
  @row_titles.each do |row_title|
    row = @rows_parsed.get_row(row_title)
    data_array = []
    data_array << column_head(row_title) if @options[:row_header] 
    data_array += row.to_a(column_titles)
    data_array << row.total(column_titles) if @options[:row_total]
    res << data_array
  end
  res
end

#build_dataObject Also known as: build_hash

return an pivot hash. data rows only



95
96
97
98
99
100
101
102
103
104
# File 'lib/rubypivot/pivot.rb', line 95

def build_data
  parse_data unless @rows_parsed
  res = {}
  @row_titles.each do |row_title|
    row = @rows_parsed.get_row(row_title)
    title = column_head(row_title)
    res[title] = row.to_a(column_titles)
  end
  res
end

#column_head(row_title) ⇒ Object



56
57
58
# File 'lib/rubypivot/pivot.rb', line 56

def column_head(row_title)
  @options[:row_lookup] ? @options[:row_lookup][row_title] : row_title
end

#column_titlesObject

Scan source data and buide titles array



43
44
45
# File 'lib/rubypivot/pivot.rb', line 43

def column_titles
  @column_titles ||= make_column_list
end

#column_titles=(new_array) ⇒ Object

Column title can be predefined by caller

Raises:



38
39
40
41
# File 'lib/rubypivot/pivot.rb', line 38

def column_titles= (new_array)
  raise PivotError, "Column title must be an array" unless new_array.is_a?(Array)
  @column_titles = new_array
end

#header_row(title = nil) ⇒ Object

Make an array



125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/rubypivot/pivot.rb', line 125

def header_row(title = nil)
  res = []
  res << "#{title}" if @options[:row_header]
  if @options[:column_lookup]
    @column_titles.each do |column|
      res << @options[:column_lookup][column]
    end
  else
    res += @column_titles
  end
  res << @options[:row_total] if @options[:row_total]
  res
end

#make_column_listObject



60
61
62
63
64
65
66
67
68
# File 'lib/rubypivot/pivot.rb', line 60

def make_column_list
  @column_titles = [] unless @column_titles
  @source_data.each do |each_line|
    title = Pivot.get_title(@column_name, each_line)
    @column_titles << title unless @column_titles.include?(title)
  end
  @column_titles.sort! if @options[:column_sort]
  @column_titles
end

#make_row_listObject



70
71
72
73
74
75
76
77
78
# File 'lib/rubypivot/pivot.rb', line 70

def make_row_list
  @row_titles = [] unless @row_titles
  @source_data.each do |each_line|
    title = Pivot.get_title(@row_name, each_line)
    @row_titles << title unless @row_titles.include?(title)
  end
  @row_titles.sort! if @options[:row_sort]
  @row_titles
end

#parse_dataObject



80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/rubypivot/pivot.rb', line 80

def parse_data
  make_column_list unless @column_titles
  make_row_list unless @row_titles
  @rows_parsed = PivotRows.new(@options)
  @source_data.each do |each_line|
    column_title = Pivot.get_title(@column_name, each_line)
    row_title = Pivot.get_title(@row_name, each_line)
    value = Pivot.get_value(@value_name, each_line)
    row = @rows_parsed.get_row(row_title) # create a new row if not exists
    row.add(column_title, value)
  end
  self
end

#row_titlesObject

Scan source data and buide titles array



52
53
54
# File 'lib/rubypivot/pivot.rb', line 52

def row_titles
  @row_titles || make_row_list
end

#row_titles=(new_array) ⇒ Object

Row title can be predefined by caller

Raises:



47
48
49
50
# File 'lib/rubypivot/pivot.rb', line 47

def row_titles= (new_array)
  raise PivotError, "Row title must be an array" unless new_array.is_a?(Array)
  @row_titles = new_array
end

#total_row(title = nil) ⇒ Object



139
140
141
142
143
144
145
# File 'lib/rubypivot/pivot.rb', line 139

def total_row(title = nil)
  parse_data unless @rows_parsed
  # title: message at title row, third(3) param is grand total true/false
  res = []
  res << title if @options[:row_header]
  res += @rows_parsed.total(@column_titles, @options[:row_total])
end