pivot_table 0.0.3 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.rvmrc CHANGED
@@ -1,21 +1,22 @@
1
- ruby_version="1.9.2"
2
- gemset_name="pivot"
1
+ #!/usr/bin/env bash
3
2
 
4
- ok="\033[10;32m"
5
- warn="\033[1;31m"
6
- reset="\033[0m"
3
+ environment_id="ruby-1.9.2-p290@pivot_table"
7
4
 
8
- if rvm list strings | grep -q "${ruby_version}" ; then
9
- rvm use ${ruby_version}
5
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
6
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
7
+ then
8
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
10
9
 
11
- if rvm gemset list | grep -q "${gemset_name}" ; then
12
- echo -e "${ok}Using the ${gemset_name} gemset${reset}"
13
- rvm gemset use ${gemset_name}
14
- else
15
- echo -e "${ok}The ${gemset_name} gemset does not exist, using global gemset${reset}"
10
+ if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
11
+ then
12
+ . "${rvm_path:-$HOME/.rvm}/hooks/after_use"
16
13
  fi
17
-
14
+ echo "RVM environment: ${environment_id}"
18
15
  else
19
- echo -e "${warn}You do not have the required Ruby installed: ${ruby_version}${reset}"
20
-
16
+ # If the environment file has not yet been created, use the RVM CLI to select.
17
+ if ! rvm --create "$environment_id"
18
+ then
19
+ echo "Failed to create RVM environment '${environment_id}'."
20
+ exit 1
21
+ fi
21
22
  fi
data/.travis.yml ADDED
@@ -0,0 +1,2 @@
1
+ rvm:
2
+ - 1.9.2
data/Gemfile CHANGED
@@ -3,12 +3,15 @@ source "http://rubygems.org"
3
3
  # Specify your gem's dependencies in pivot.gemspec
4
4
  gemspec
5
5
 
6
+ gem 'rake'
7
+
6
8
  group :development, :test do
7
9
  gem 'autotest'
8
- gem 'autotest-growl'
10
+ #gem 'autotest-growl'
9
11
  gem 'autotest-notification'
10
12
  gem 'bundler'
11
13
  gem 'launchy'
12
14
  gem 'rcov'
13
15
  gem 'rspec'
16
+ gem 'shoulda-matchers'
14
17
  end
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- Pivot Table
1
+ Pivot Table [![Build Status](https://secure.travis-ci.org/edjames/pivot_table.png)](http://travis-ci.org/edjames/pivot_table)
2
2
  ===========
3
3
 
4
4
  A handy tool for transforming a dataset into a spreadsheet-style pivot table.
@@ -7,7 +7,7 @@ Why make this?
7
7
  --------------
8
8
 
9
9
  One of the most powerful and underrated features of spreadhseet packages is their ability to create pivot tables. I'm often asked
10
- to replicate this functionality in a web application...
10
+ to replicate this functionality in a web application, so I decided to share. This is a simple gem for a specific job, I hope it helps.
11
11
 
12
12
  Installation
13
13
  ------------
@@ -26,47 +26,70 @@ At the very least, you will need to provide four things to create a pivot table.
26
26
  * a dataset (this doesn't necessarily have to be an ActiveRecord dataset, but it should at least behave like ActiveRecord e.g. OpenStruct)
27
27
  * the method to be used as column names
28
28
  * the method to be used as row names
29
- * the method to be used as the pivot
30
-
31
- Let's say you have a dataset that looks like this (I'll use OpenStruct, but this could easily be ActiveRecord, or even a custom object):
32
-
33
- my_data = []
34
- my_data << OpenStruct.new(:city => 'London', :quarter => 'Q1', :sales => 100)
35
- my_data << OpenStruct.new(:city => 'London', :quarter => 'Q2', :sales => 200)
36
- my_data << OpenStruct.new(:city => 'London', :quarter => 'Q3', :sales => 300)
37
- my_data << OpenStruct.new(:city => 'London', :quarter => 'Q4', :sales => 400)
38
- my_data << OpenStruct.new(:city => 'New York', :quarter => 'Q1', :sales => 10)
39
- my_data << OpenStruct.new(:city => 'New York', :quarter => 'Q2', :sales => 20)
40
- my_data << OpenStruct.new(:city => 'New York', :quarter => 'Q3', :sales => 30)
41
- my_data << OpenStruct.new(:city => 'New York', :quarter => 'Q4', :sales => 40)
42
-
43
- You can then generate a pivot table like so...
44
-
45
- p = PivotTable::Table.new do |p|
46
- p.data = my_data
47
- p.column = :quarter
48
- p.row = :city
49
- p.pivot_on = :sales
29
+
30
+ Let's say you have a collection of Order objects that looks like this:
31
+
32
+ obj_1 = Order.new(:city => 'London', :quarter => 'Q1')
33
+ obj_2 = Order.new(:city => 'London', :quarter => 'Q2')
34
+ obj_3 = Order.new(:city => 'London', :quarter => 'Q3')
35
+ obj_4 = Order.new(:city => 'London', :quarter => 'Q4')
36
+ obj_5 = Order.new(:city => 'New York', :quarter => 'Q1')
37
+ obj_6 = Order.new(:city => 'New York', :quarter => 'Q2')
38
+ obj_7 = Order.new(:city => 'New York', :quarter => 'Q3')
39
+ obj_8 = Order.new(:city => 'New York', :quarter => 'Q4')
40
+
41
+ data = [ obj_1, obj_2, obj_3, obj_4, obj_5, obj_6, obj_7, obj_8 ]
42
+
43
+ Instantiate a new PivotTable::Grid object like this...
44
+
45
+ grid = PivotTable::Grid.new do |g|
46
+ g.sourcedata = data
47
+ g.column_name = :quarter
48
+ g.row_name = :city
50
49
  end
51
- p.generate
52
50
 
53
- ...which will give you a hash that looks like this...
54
51
 
55
- {
56
- :headers => ['', 'Q1', 'Q2', 'Q3', 'Q4', 'Total'],
57
- :rows => [
58
- ['London', 100, 200, 300, 400, 1000],
59
- ['New York', 10, 20, 30, 40, 100]
60
- ],
61
- :totals => ['Total', 110, 220, 330, 440, 1100]
62
- }
52
+ All you have to do now is build the grid...
53
+
54
+ g.build
55
+
56
+ This will give you a logical grid (represented by an two-dimensional array) which can be likened to this table:
57
+
58
+ --------------------------------------------
59
+ | | Q1 | Q2 | Q3 | Q4 |
60
+ |----------|--------------------------------
61
+ | London | obj_1 | obj_2 | obj_3 | obj_4 |
62
+ | New York | obj_5 | obj_6 | obj_7 | obj_8 |
63
+ --------------------------------------------
64
+
65
+ Then you have the following aspects of the pivot table grid available to you...
63
66
 
64
- ...which makes it easy-peasy to print a pivot table that looks like this...
67
+ g.row_headers => ['London', 'New York']
68
+ g.rows.length => 2
65
69
 
66
- Q1 Q2 Q3 Q4 Total
67
- London 100 200 300 400 1000
68
- New York 10 20 30 40 100
69
- Total 110 220 330 440 1100
70
+ g.rows[0].header => 'London'
71
+ g.rows[0].data => [obj_1, obj_2, obj_3, obj_4]
72
+
73
+ g.rows[1].header => 'New York'
74
+ g.rows[1].data => [obj_5, obj_6, obj_7, obj_8]
75
+
76
+ g.column_headers => ['Q1', 'Q2', 'Q3', 'Q4']
77
+ g.columns.length => 4
78
+
79
+ g.columns[0].header => 'Q1'
80
+ g.columns[0].data => [obj_1, obj_5]
81
+
82
+ g.columns[1].header => 'Q2'
83
+ g.columns[1].data => [obj_2, obj_6]
84
+
85
+ g.columns[2].header => 'Q3'
86
+ g.columns[2].data => [obj_3, obj_7]
87
+
88
+ g.columns[3].header => 'Q4'
89
+ g.columns[3].data => [obj_4, obj_8]
90
+
91
+ The API should give you a lot of flexibility with regards to rendering this information in your views.
92
+ E.g. The rows and columns collections make it very easy to produce horizontal, vertical and overall total values.
70
93
 
71
94
  Ah, that's better.
72
95
 
@@ -76,6 +99,12 @@ Still to come
76
99
  PivotTable is still in the very early stages of development. As my personal needs for evolve, I'll update the gem with new functionality accordingly.
77
100
  Feel free to fork and/or suggest new features.
78
101
 
102
+ Ruby 1.9 only...for now
103
+ ----------------
104
+
105
+ Right now PivotTable only supports Ruby 1.9. If you need support for 1.8 please feel free to fork and merge. I will not however be adding
106
+ support for 1.8.
107
+
79
108
  Contributing to PivotTable
80
109
  ---------------------
81
110
 
data/Rakefile CHANGED
@@ -1,2 +1,7 @@
1
1
  require 'bundler/gem_tasks'
2
2
  Bundler::GemHelper.install_tasks
3
+
4
+ desc "Fix the xml column types from a SqlServer database in schema.rb"
5
+ task :default do
6
+ exec 'rspec spec'
7
+ end
data/lib/pivot_table.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  $: << File.dirname(__FILE__)
2
- require "pivot_table/table"
2
+
3
+ require "pivot_table/grid"
4
+ require "pivot_table/column"
5
+ require "pivot_table/row"
3
6
 
4
7
  module PivotTable
5
- VERSION = "0.0.3"
8
+ VERSION = "0.1.1"
6
9
  end
@@ -0,0 +1,17 @@
1
+ module PivotTable
2
+ class Column
3
+
4
+ ACCESSORS = [:header, :data, :total]
5
+
6
+ ACCESSORS.each do |a|
7
+ self.send(:attr_accessor, a)
8
+ end
9
+
10
+ def initialize(options = {})
11
+ ACCESSORS.each do |a|
12
+ self.send("#{a}=", options[a]) if options.has_key?(a)
13
+ end
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,66 @@
1
+ module PivotTable
2
+ class Grid
3
+
4
+ attr_accessor :source_data, :row_name, :column_name
5
+ attr_reader :columns, :rows, :data_grid
6
+
7
+ def initialize(&block)
8
+ yield(self) if block_given?
9
+ end
10
+
11
+ def build
12
+ populate_grid
13
+ build_rows
14
+ build_columns
15
+ self
16
+ end
17
+
18
+ def build_rows
19
+ @rows = []
20
+ @data_grid.each_with_index do |data, index|
21
+ @rows << Row.new(:header => row_headers[index], :data => data)
22
+ end
23
+ end
24
+
25
+ def build_columns
26
+ @columns = []
27
+ @data_grid.transpose.each_with_index do |data, index|
28
+ @columns << Column.new(:header => column_headers[index], :data => data)
29
+ end
30
+ end
31
+
32
+ def column_headers
33
+ headers @column_name
34
+ end
35
+
36
+ def row_headers
37
+ headers @row_name
38
+ end
39
+
40
+ def prepare_grid
41
+ @data_grid = []
42
+ row_headers.count.times do
43
+ @data_grid << column_headers.count.times.inject([]) { |col| col << nil }
44
+ end
45
+ @data_grid
46
+ end
47
+
48
+ def populate_grid
49
+ prepare_grid
50
+ row_headers.each_with_index do |row, row_index|
51
+ current_row = []
52
+ column_headers.each_with_index do |col, col_index|
53
+ current_row[col_index] = @source_data.find { |item| item.send(row_name) == row && item.send(column_name) == col }
54
+ end
55
+ @data_grid[row_index] = current_row
56
+ end
57
+ @data_grid
58
+ end
59
+
60
+ private
61
+ def headers method
62
+ @source_data.collect { |c| c.send method }.uniq.sort
63
+ end
64
+
65
+ end
66
+ end
@@ -0,0 +1,17 @@
1
+ module PivotTable
2
+ class Row
3
+
4
+ ACCESSORS = [:header, :data, :total]
5
+
6
+ ACCESSORS.each do |a|
7
+ self.send(:attr_accessor, a)
8
+ end
9
+
10
+ def initialize(options = {})
11
+ ACCESSORS.each do |a|
12
+ self.send("#{a}=", options[a]) if options.has_key?(a)
13
+ end
14
+ end
15
+
16
+ end
17
+ end
data/pivot_table.gemspec CHANGED
@@ -9,9 +9,10 @@ Gem::Specification.new do |s|
9
9
  s.email = Base64.decode64("ZWQuamFtZXMuZW1haWxAZ21haWwuY29t\n")
10
10
  s.homepage = "https://github.com/edjames/pivot_table"
11
11
  s.summary = "pivot_table-#{s.version}"
12
- s.description = "Transform an ActiveRecord-ish data set into pivot table"
12
+ s.description = "Transform an ActiveRecord-ish data set into a pivot table of objects"
13
13
 
14
14
  s.platform = Gem::Platform::RUBY
15
+ s.required_ruby_version = '>= 1.9'
15
16
 
16
17
  s.rubyforge_project = "pivot_table"
17
18
  s.rubygems_version = ">= 1.6.1"
@@ -0,0 +1,23 @@
1
+ require "spec_helper"
2
+
3
+ module PivotTable
4
+ describe Column do
5
+
6
+ let(:klass) { Column }
7
+
8
+ before { @instance = klass.new }
9
+
10
+ it { should respond_to :header }
11
+ it { should respond_to :data }
12
+ it { should respond_to :total }
13
+
14
+ context 'initialize with hash' do
15
+ subject { klass.new(header: 'header', data: 'data', total: 'total')}
16
+
17
+ its(:header) { should == 'header' }
18
+ its(:data) { should == 'data' }
19
+ its(:total) { should == 'total' }
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,112 @@
1
+ require 'spec_helper'
2
+
3
+ module PivotTable
4
+ describe Grid do
5
+ def build_object(id, row, column)
6
+ OpenStruct.new id: id, row_name: row, column_name: column
7
+ end
8
+
9
+ let(:d1) { build_object(1, 'r1', 'c1') }
10
+ let(:d2) { build_object(2, 'r1', 'c2') }
11
+ let(:d3) { build_object(3, 'r1', 'c3') }
12
+ let(:d4) { build_object(4, 'r2', 'c1') }
13
+ let(:d5) { build_object(5, 'r2', 'c2') }
14
+ let(:d6) { build_object(6, 'r2', 'c3') }
15
+
16
+ let(:data) { [d1, d2, d3, d4, d5, d6] }
17
+
18
+ let(:column_headers) { %w(c1 c2 c3) }
19
+ let(:row_headers) { %w(r1 r2) }
20
+ let(:row_0) { [d1, d2, d3] }
21
+ let(:row_1) { [d4, d5, d6] }
22
+ let(:column_0) { [d1, d4] }
23
+ let(:column_1) { [d2, d5] }
24
+ let(:column_2) { [d3, d6] }
25
+
26
+ let(:instance) do
27
+ Grid.new do |g|
28
+ g.source_data = data
29
+ g.row_name = :row_name
30
+ g.column_name = :column_name
31
+ end
32
+ end
33
+
34
+ context 'accessors' do
35
+ subject { Grid.new }
36
+ it { should respond_to :source_data }
37
+ it { should respond_to :row_name }
38
+ it { should respond_to :column_name }
39
+ it { should respond_to :columns }
40
+ it { should respond_to :rows }
41
+ end
42
+
43
+ describe 'build' do
44
+ subject { instance.build }
45
+ its(:class) { should == Grid }
46
+ end
47
+
48
+ describe 'columns' do
49
+ let(:build_result) { instance.build }
50
+ specify { build_result.columns.length.should == 3 }
51
+
52
+ context 'column headers' do
53
+ subject { build_result.column_headers }
54
+ it { should == column_headers }
55
+ end
56
+
57
+ context '1st column' do
58
+ subject { build_result.columns[0] }
59
+ its(:header) { should == column_headers[0] }
60
+ its(:data) { should = column_0 }
61
+ end
62
+
63
+ context '2nd column' do
64
+ subject { build_result.columns[1] }
65
+ its(:header) { should == column_headers[1] }
66
+ its(:data) { should = column_1 }
67
+ end
68
+
69
+ context '3rd column' do
70
+ subject { build_result.columns[2] }
71
+ its(:header) { should == column_headers[2] }
72
+ its(:data) { should = column_2 }
73
+ end
74
+ end
75
+
76
+ describe 'rows' do
77
+ let(:build_result) { instance.build }
78
+ specify { build_result.rows.length.should == 2 }
79
+
80
+ context 'row headers' do
81
+ subject { build_result.row_headers }
82
+ it { should == row_headers }
83
+ end
84
+
85
+ context '1st row' do
86
+ subject { build_result.rows[0] }
87
+ its(:header) { should == row_headers[0] }
88
+ its(:data) { should = row_0 }
89
+ end
90
+
91
+ context '2nd row' do
92
+ subject { build_result.rows[1] }
93
+ its(:header) { should == row_headers[1] }
94
+ its(:data) { should = row_1 }
95
+ end
96
+ end
97
+
98
+ describe 'data grid' do
99
+ let(:build_result) { instance.build }
100
+
101
+ context 'preparing the grid' do
102
+ subject { build_result.prepare_grid }
103
+ it { should == [[nil, nil, nil], [nil, nil, nil]] }
104
+ end
105
+
106
+ context 'populating the grid' do
107
+ subject { build_result.data_grid }
108
+ it { should == [[d1, d2, d3], [d4, d5, d6]] }
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,23 @@
1
+ require "spec_helper"
2
+
3
+ module PivotTable
4
+ describe Row do
5
+
6
+ let(:klass) { Row }
7
+
8
+ before { @instance = klass.new }
9
+
10
+ it { should respond_to :header }
11
+ it { should respond_to :data }
12
+ it { should respond_to :total }
13
+
14
+ context 'initialize with hash' do
15
+ subject { klass.new(header: 'header', data: 'data', total: 'total')}
16
+
17
+ its(:header) { should == 'header' }
18
+ its(:data) { should == 'data' }
19
+ its(:total) { should == 'total' }
20
+ end
21
+
22
+ end
23
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pivot_table
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,9 +9,9 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-08-29 00:00:00.000000000Z
12
+ date: 2011-09-28 00:00:00.000000000Z
13
13
  dependencies: []
14
- description: Transform an ActiveRecord-ish data set into pivot table
14
+ description: Transform an ActiveRecord-ish data set into a pivot table of objects
15
15
  email: ed.james.email@gmail.com
16
16
  executables: []
17
17
  extensions: []
@@ -20,15 +20,20 @@ files:
20
20
  - .gitignore
21
21
  - .rspec
22
22
  - .rvmrc
23
+ - .travis.yml
23
24
  - CHANGELOG.md
24
25
  - Gemfile
25
26
  - LICENSE
26
27
  - README.md
27
28
  - Rakefile
28
29
  - lib/pivot_table.rb
29
- - lib/pivot_table/table.rb
30
+ - lib/pivot_table/column.rb
31
+ - lib/pivot_table/grid.rb
32
+ - lib/pivot_table/row.rb
30
33
  - pivot_table.gemspec
31
- - spec/pivot_table/table_spec.rb
34
+ - spec/pivot_table/column_spec.rb
35
+ - spec/pivot_table/grid_spec.rb
36
+ - spec/pivot_table/row_spec.rb
32
37
  - spec/spec_helper.rb
33
38
  homepage: https://github.com/edjames/pivot_table
34
39
  licenses: []
@@ -41,7 +46,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
41
46
  requirements:
42
47
  - - ! '>='
43
48
  - !ruby/object:Gem::Version
44
- version: '0'
49
+ version: '1.9'
45
50
  required_rubygems_version: !ruby/object:Gem::Requirement
46
51
  none: false
47
52
  requirements:
@@ -50,8 +55,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
50
55
  version: '0'
51
56
  requirements: []
52
57
  rubyforge_project: pivot_table
53
- rubygems_version: 1.8.10
58
+ rubygems_version: 1.8.6
54
59
  signing_key:
55
60
  specification_version: 3
56
- summary: pivot_table-0.0.3
61
+ summary: pivot_table-0.1.1
57
62
  test_files: []
@@ -1,73 +0,0 @@
1
- module PivotTable
2
- class Table
3
-
4
- attr_accessor :data, :column, :row, :pivot_on
5
-
6
- def initialize(&block)
7
- yield(self) if block_given?
8
- end
9
-
10
- def column_headers
11
- @data.collect { |c| c.send @column }.uniq.sort
12
- end
13
-
14
- def row_headers
15
- @data.collect { |r| r.send @row }.uniq.sort
16
- end
17
-
18
- def initialize_grid(rows, columns, default_value = 0)
19
- @grid = []
20
- rows.times do
21
- @grid << columns.times.inject([]) { |col| col << default_value }
22
- end
23
- @grid
24
- end
25
-
26
- def matching_data(row_header, column_header)
27
- data.select { |item| item.send(@row) == row_header && item.send(@column) == column_header }
28
- end
29
-
30
- def populate_grid
31
- row_headers.each_with_index do |row_header, row_index|
32
- column_headers.each_with_index do |column_header, column_index|
33
- collected = matching_data row_header, column_header
34
- total = collected.inject(0) { |sum, item| sum += item.send(@pivot_on) }
35
- @grid[row_index][column_index] += total
36
- end
37
- end
38
- @grid
39
- end
40
-
41
- def row_sum row
42
- row.inject(0) { |sum, value| sum += value }
43
- end
44
-
45
- def calculate_row_totals
46
- @grid.each { |row| row << row_sum(row) }
47
- end
48
-
49
- def add_row_headers
50
- @grid.each_with_index do |row, index|
51
- row.unshift row_headers[index]
52
- end
53
- end
54
-
55
- def calculate_column_totals data
56
- numeric_data = data.dup
57
- numeric_data.transpose.map { |row| row_sum row }
58
- end
59
-
60
- def generate
61
- initialize_grid row_headers.size, column_headers.size, 0
62
- populate_grid
63
- calculate_row_totals
64
- totals = calculate_column_totals @grid
65
-
66
- {
67
- :headers => ['', column_headers, 'Total'].flatten,
68
- :rows => add_row_headers,
69
- :totals => ['Total', totals].flatten
70
- }
71
- end
72
- end
73
- end
@@ -1,120 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module PivotTable
4
- describe Table do
5
- context 'accessors' do
6
- subject { Table.new }
7
- it { should respond_to :data }
8
- it { should respond_to :column }
9
- it { should respond_to :row }
10
- it { should respond_to :pivot_on }
11
- end
12
-
13
- context 'instantiate using explicit block form' do
14
- subject do
15
- Table.new do |i|
16
- i.data = :data
17
- i.column = :column
18
- i.row = :row
19
- i.pivot_on = :pivot_on
20
- end
21
- end
22
-
23
- specify { subject.data.should == :data }
24
- specify { subject.column.should == :column }
25
- specify { subject.row.should == :row }
26
- specify { subject.pivot_on.should == :pivot_on }
27
- end
28
-
29
- before do
30
- @data = []
31
- @data << OpenStruct.new(:city => 'London', :quarter => 'Q1', :sales => 100)
32
- @data << OpenStruct.new(:city => 'London', :quarter => 'Q2', :sales => 200)
33
- @data << OpenStruct.new(:city => 'London', :quarter => 'Q3', :sales => 300)
34
- @data << OpenStruct.new(:city => 'London', :quarter => 'Q4', :sales => 400)
35
- @data << OpenStruct.new(:city => 'Cape Town', :quarter => 'Q1', :sales => 5)
36
- @data << OpenStruct.new(:city => 'Cape Town', :quarter => 'Q1', :sales => 15)
37
- @data << OpenStruct.new(:city => 'Cape Town', :quarter => 'Q1', :sales => 30)
38
- @data << OpenStruct.new(:city => 'New York', :quarter => 'Q1', :sales => 10)
39
- @data << OpenStruct.new(:city => 'New York', :quarter => 'Q2', :sales => 20)
40
- @data << OpenStruct.new(:city => 'New York', :quarter => 'Q3', :sales => 30)
41
- @data << OpenStruct.new(:city => 'New York', :quarter => 'Q4', :sales => 10)
42
- @data << OpenStruct.new(:city => 'New York', :quarter => 'Q4', :sales => 30)
43
- @instance = Table.new do |i|
44
- i.data = @data
45
- i.column = :quarter
46
- i.row = :city
47
- i.pivot_on = :sales
48
- end
49
- end
50
-
51
- subject { @instance }
52
-
53
- context 'column headers' do
54
- subject { @instance.column_headers }
55
- it { should == ['Q1', 'Q2', 'Q3', 'Q4'] }
56
- end
57
-
58
- context 'row headers' do
59
- subject { @instance.row_headers }
60
- it { should == ['Cape Town', 'London', 'New York'] }
61
- end
62
-
63
- context 'initializing the grid' do
64
- before do
65
- @expected_result = [
66
- [0, 0, 0],
67
- [0, 0, 0]
68
- ]
69
- end
70
- subject { @instance.initialize_grid 2, 3, 0 }
71
- it { should == @expected_result }
72
- end
73
-
74
- context 'matching data' do
75
- context 'single matching data item' do
76
- subject { @instance.matching_data 'London', 'Q1' }
77
- specify { subject.size.should == 1 }
78
- specify { subject.first.should == @data.first }
79
- end
80
-
81
- context 'multiple matching data items' do
82
- subject { @instance.matching_data 'Cape Town', 'Q1' }
83
- specify { subject.size.should == 3 }
84
- specify { subject[0].should == @data[4] }
85
- specify { subject[1].should == @data[5] }
86
- specify { subject[2].should == @data[6] }
87
- end
88
- end
89
-
90
- context 'aggregating the data in the grid' do
91
- before do
92
- @instance.initialize_grid 3, 4, 0
93
- @expected_result = [
94
- [50, 0, 0, 0],
95
- [100, 200, 300, 400],
96
- [10, 20, 30, 40]
97
- ]
98
- end
99
- subject { @instance.populate_grid }
100
- it { should == @expected_result }
101
- end
102
-
103
- context 'generate' do
104
- before do
105
- @expected_result = {
106
- :headers => ['', 'Q1', 'Q2', 'Q3', 'Q4', 'Total'],
107
- :rows => [
108
- ['Cape Town', 50, 0, 0, 0, 50],
109
- ['London', 100, 200, 300, 400, 1000],
110
- ['New York', 10, 20, 30, 40, 100]
111
- ],
112
- :totals => ['Total', 160, 220, 330, 440, 1150]
113
- }
114
- end
115
- subject { @instance.generate }
116
- it { should == @expected_result }
117
- end
118
-
119
- end
120
- end