crosstab 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +4 -0
- data/Manifest.txt +23 -0
- data/README.txt +133 -0
- data/Rakefile +17 -0
- data/lib/crosstab.rb +25 -0
- data/lib/crosstab/banner.rb +90 -0
- data/lib/crosstab/cell.rb +162 -0
- data/lib/crosstab/column.rb +64 -0
- data/lib/crosstab/crosstab.rb +243 -0
- data/lib/crosstab/extensions.rb +26 -0
- data/lib/crosstab/generic.rb +83 -0
- data/lib/crosstab/group.rb +28 -0
- data/lib/crosstab/row.rb +65 -0
- data/lib/crosstab/table.rb +85 -0
- data/test/test_banner.rb +81 -0
- data/test/test_cell.rb +95 -0
- data/test/test_column.rb +60 -0
- data/test/test_crosstab.rb +214 -0
- data/test/test_extensions.rb +12 -0
- data/test/test_group.rb +67 -0
- data/test/test_missing.rb +75 -0
- data/test/test_row.rb +60 -0
- data/test/test_table.rb +67 -0
- metadata +87 -0
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift "../lib" if __FILE__ == $0
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'crosstab'
|
5
|
+
|
6
|
+
class ExtensionTests < Test::Unit::TestCase
|
7
|
+
def test_array_to_freq_chart
|
8
|
+
@array = [nil, "a", "a", "a", "b", "b", "b", nil, "c"]
|
9
|
+
assert_equal [[1,nil],[3,"a"],[3,"b"],[1,nil],[1,"c"]], @array.to_freq_chart
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
data/test/test_group.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
$LOAD_PATH.unshift "../lib" if __FILE__ == $0
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
class GroupTests < Test::Unit::TestCase
|
6
|
+
# Same tests as Crosstab::Row
|
7
|
+
def setup
|
8
|
+
@group = Crosstab::Group.new
|
9
|
+
end
|
10
|
+
|
11
|
+
# Responds to these public methods
|
12
|
+
def test_respond_method
|
13
|
+
[:title, :qualifies?, :cells, :children, :printed?].each do |method|
|
14
|
+
assert_respond_to @group, method, "Hey, an instantiated group should have a `#{method}` method."
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Test defaults for reader methods
|
19
|
+
def test_default_title
|
20
|
+
assert_nil @group.title
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_default_cells
|
24
|
+
assert_equal [], @group.cells
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_default_children
|
28
|
+
assert_equal [], @group.cells
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_default_printed?
|
32
|
+
assert_equal false, @group.printed?
|
33
|
+
end
|
34
|
+
|
35
|
+
# Test behavior of setter methods
|
36
|
+
def test_set_title
|
37
|
+
@group.title "Test Title"
|
38
|
+
assert_equal "Test Title", @group.title
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_qualifies?
|
42
|
+
# So lazy. Totally cheating.
|
43
|
+
@group.children << Crosstab::Row.new("Male", :a => 1)
|
44
|
+
@group.children << Crosstab::Row.new("Female", :a => 2)
|
45
|
+
|
46
|
+
assert_equal true, @group.qualifies?(:a => 1)
|
47
|
+
assert_equal true, @group.qualifies?(:a => 2)
|
48
|
+
assert_equal false, @group.qualifies?(:a => 3)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_set_cells
|
52
|
+
@group.cells [Crosstab::Cell.new(:base => 100, :frequency => 50)]
|
53
|
+
assert_equal 1, @group.cells.length
|
54
|
+
assert_equal 0.5, @group.cells.first.percentage
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_set_children
|
58
|
+
@group.children [Crosstab::Row.new("Row title", :a => 4)]
|
59
|
+
assert_equal "Row title", @group.children.first.title
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_set_printed?
|
63
|
+
@group.printed? true
|
64
|
+
assert_equal true, @group.printed?
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
$LOAD_PATH.unshift "../lib" if __FILE__ == $0
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
class TestMissing < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def test_missing_ranking
|
8
|
+
assert false
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_missing_norank
|
12
|
+
assert false
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_missing_mean
|
16
|
+
assert false
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_missing_std_dev
|
20
|
+
assert false
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_missing_std_err
|
24
|
+
assert false
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_missing_median
|
28
|
+
assert false
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_missing_populate
|
32
|
+
assert false
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_recoding
|
36
|
+
assert false
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_not_happy_with_column
|
40
|
+
assert false
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_not_happy_with_crosstab_adding_cells_to_rows
|
44
|
+
# Why did I intersperse the report with the rows and columns? It would be much cleaner to simply return an array of results
|
45
|
+
# from the calculate method. Then we can add the detailed reporting shit later, or to another gem like crosstab::detailed.
|
46
|
+
#
|
47
|
+
# like...
|
48
|
+
#
|
49
|
+
# my_crosstab.report true
|
50
|
+
# [:table, "Table 1"],
|
51
|
+
# [:title, "Q.A Gender:"],
|
52
|
+
# [:headers, nil,"Male","Female"],
|
53
|
+
# [:baseline, "(Base)",[10],[10]],
|
54
|
+
# [:row, "Male",[10,"100%"],[0,"0%"]],
|
55
|
+
# [:row, "Female",[0,"0%"],[10,"100%"]]]
|
56
|
+
#
|
57
|
+
# or the default...
|
58
|
+
#
|
59
|
+
# my_crosstab.report false
|
60
|
+
#
|
61
|
+
# ["Table 1",
|
62
|
+
# "Q.A Gender:",
|
63
|
+
# [nil,"Male","Female"],
|
64
|
+
# ["(Base)",[10],[10]],
|
65
|
+
# ["Male",[10,"100%"],[0,"0%"]],
|
66
|
+
# ["Female",[0,"0%"],[10,"100%"]]]
|
67
|
+
#
|
68
|
+
# Add in mean, median, std. dev., std. error, sigtesting and you've got yourself a lightweight crosstab system.
|
69
|
+
# Next version, add the Uncle-style report.
|
70
|
+
#
|
71
|
+
# Also keep in mind that each class is its own library. None of the classes get to talk to any others except for Crosstab,
|
72
|
+
# which ties them together. And it shouldn't get to write data to any of them in the calculate or report methods.
|
73
|
+
assert false
|
74
|
+
end
|
75
|
+
end
|
data/test/test_row.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
$LOAD_PATH.unshift "../lib" if __FILE__ == $0
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
|
6
|
+
class RowTests < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
@row = Crosstab::Row.new
|
9
|
+
end
|
10
|
+
|
11
|
+
# Responds to these public methods
|
12
|
+
def test_respond_methods
|
13
|
+
[:title, :qualification, :qualifies?, :cells, :group].each do |method|
|
14
|
+
assert_respond_to @row, method, "Hey, an instantiated row should have a `#{method}` method."
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Test defaults for reader methods
|
19
|
+
def test_default_title
|
20
|
+
assert_nil @row.title
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_default_qualifies?
|
24
|
+
assert_equal true, @row.qualifies?(Hash.new)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_default_cells
|
28
|
+
assert_equal [], @row.cells
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_default_group
|
32
|
+
assert_equal nil, @row.group
|
33
|
+
end
|
34
|
+
|
35
|
+
# Test behavior of setter methods
|
36
|
+
def test_set_title
|
37
|
+
@row.title "Test Title"
|
38
|
+
assert_equal "Test Title", @row.title
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_set_qualification
|
42
|
+
@row.qualification :a => 1
|
43
|
+
|
44
|
+
assert_equal true, @row.qualifies?(:a => 1, :b => 1)
|
45
|
+
assert_equal false, @row.qualifies?(:a => 2, :b => 1)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_set_cells
|
49
|
+
@row.cells [Crosstab::Cell.new(:base => 100, :frequency => 50)]
|
50
|
+
assert_equal 1, @row.cells.length
|
51
|
+
assert_equal 0.5, @row.cells.first.percentage
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_set_group
|
55
|
+
@row.group Crosstab::Group.new("Group Title")
|
56
|
+
assert_equal "Group Title", @row.group.title
|
57
|
+
assert_equal [ @row ], @row.group.children
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
data/test/test_table.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
$LOAD_PATH.unshift "../lib" if __FILE__ == $0
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
class Test__CrosstabTable < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@table = Crosstab::Table.new
|
8
|
+
end
|
9
|
+
|
10
|
+
# Responds to these public methods
|
11
|
+
def test_respond_methods
|
12
|
+
[:title, :qualification, :qualifies?, :rows, :row, :group].each do |method|
|
13
|
+
assert_respond_to @table, method, "Hey, an instantiated table should have a `#{method}` method."
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Test defaults for reader methods
|
18
|
+
def test_default_title
|
19
|
+
assert_nil @table.title
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_default_qualifies?
|
23
|
+
assert_equal true, @table.qualifies?(Hash.new)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_default_rows
|
27
|
+
assert_equal [], @table.rows
|
28
|
+
end
|
29
|
+
|
30
|
+
# Test behavior of setter methods
|
31
|
+
def test_set_title
|
32
|
+
@table.title "Test Title"
|
33
|
+
assert_equal "Test Title", @table.title
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_set_qualification
|
37
|
+
@table.qualification :a => 1
|
38
|
+
|
39
|
+
assert_equal true, @table.qualifies?(:a => 1, :b => 1)
|
40
|
+
assert_equal false, @table.qualifies?(:a => 2, :b => 1)
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_set_row
|
44
|
+
@table.row "New Row", :a => 2
|
45
|
+
|
46
|
+
assert_equal 1, @table.rows.length
|
47
|
+
assert_kind_of Crosstab::Row, @table.rows.first
|
48
|
+
assert_equal "New Row", @table.rows.first.title
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_set_group
|
52
|
+
@table.group "Gender" do
|
53
|
+
row "Male", :a => 1
|
54
|
+
row "Female", :a => 2
|
55
|
+
end
|
56
|
+
|
57
|
+
assert_equal 2, @table.rows.length
|
58
|
+
assert_kind_of Crosstab::Row, @table.rows.first
|
59
|
+
assert_kind_of Crosstab::Row, @table.rows.last
|
60
|
+
|
61
|
+
assert_equal "Male", @table.rows.first.title
|
62
|
+
assert_equal "Female", @table.rows.last.title
|
63
|
+
|
64
|
+
assert_equal "Gender", @table.rows.first.group.title
|
65
|
+
assert_equal "Gender", @table.rows.last.group.title
|
66
|
+
end
|
67
|
+
end
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.3
|
3
|
+
specification_version: 1
|
4
|
+
name: crosstab
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.1.0
|
7
|
+
date: 2007-10-18 00:00:00 -07:00
|
8
|
+
summary: Crosstab is a library for generating formatted pivot tables.
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: mjudge@surveycomplete.com
|
12
|
+
homepage: " by Michael Judge <mjudge@surveycomplete.com>"
|
13
|
+
rubyforge_project: crosstab
|
14
|
+
description: "== FEATURES: * Input your data as an array of hashes * Input a report layout, built using a Ruby DSL * Outputs ASCII pivot tables suitable for fast reports * Pretty fast: takes less than a second to process 1,000 records of data by a report with 100 rows and 10 columns. == SYNOPSIS: require 'crosstab' data = [{:gender => \"M\", :age => 1}, {:gender => \"F\", :age => 2}, {:gender => \"M\", :age => 3}] my_crosstab = crosstab data do table do title \"Q.A Gender:\" row \"Male\", :gender => \"M\" row \"Female\", :gender => \"F\" end table do title \"Q.B Age:\" group \"18 - 54\" do row \"18 - 34\", :age => 1 row \"35 - 54\", :age => 2 end row \"55 or older\", :age => 3 end banner do column \"Total\" group \"Gender\" do column \"Male\", :gender => \"M\" column \"Female\", :gender => \"F\" end end end puts my_crosstab.to_s == REPORT: # puts my_crosstab.to_s Table 1 Q.A Gender: Gender ---------------- Total Male Female (A) (B) (C) ------- ------- ------- (BASE) 3 2 1 Male 2 2 -- 67% 100% Female 1 -- 1 33% 100% ------------------------------------------------------------------------ Table 2 Q.B Age: Gender ---------------- Total Male Female (A) (B) (C) ------- ------- ------- (BASE) 3 2 1 18 - 54 2 1 1 ----------------------------- 67% 50% 100% 18 - 34 1 1 -- 33% 50% 35 - 54 1 -- 1 33% 100% 55 or older 1 1 -- 33% 50%"
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Ryan Davis
|
31
|
+
files:
|
32
|
+
- History.txt
|
33
|
+
- Manifest.txt
|
34
|
+
- README.txt
|
35
|
+
- Rakefile
|
36
|
+
- lib/crosstab.rb
|
37
|
+
- lib/crosstab/banner.rb
|
38
|
+
- lib/crosstab/cell.rb
|
39
|
+
- lib/crosstab/column.rb
|
40
|
+
- lib/crosstab/crosstab.rb
|
41
|
+
- lib/crosstab/extensions.rb
|
42
|
+
- lib/crosstab/generic.rb
|
43
|
+
- lib/crosstab/group.rb
|
44
|
+
- lib/crosstab/row.rb
|
45
|
+
- lib/crosstab/table.rb
|
46
|
+
- test/test_banner.rb
|
47
|
+
- test/test_cell.rb
|
48
|
+
- test/test_column.rb
|
49
|
+
- test/test_crosstab.rb
|
50
|
+
- test/test_extensions.rb
|
51
|
+
- test/test_group.rb
|
52
|
+
- test/test_missing.rb
|
53
|
+
- test/test_row.rb
|
54
|
+
- test/test_table.rb
|
55
|
+
test_files:
|
56
|
+
- test/test_banner.rb
|
57
|
+
- test/test_cell.rb
|
58
|
+
- test/test_column.rb
|
59
|
+
- test/test_crosstab.rb
|
60
|
+
- test/test_extensions.rb
|
61
|
+
- test/test_group.rb
|
62
|
+
- test/test_missing.rb
|
63
|
+
- test/test_row.rb
|
64
|
+
- test/test_table.rb
|
65
|
+
rdoc_options:
|
66
|
+
- --main
|
67
|
+
- README.txt
|
68
|
+
extra_rdoc_files:
|
69
|
+
- History.txt
|
70
|
+
- Manifest.txt
|
71
|
+
- README.txt
|
72
|
+
executables: []
|
73
|
+
|
74
|
+
extensions: []
|
75
|
+
|
76
|
+
requirements: []
|
77
|
+
|
78
|
+
dependencies:
|
79
|
+
- !ruby/object:Gem::Dependency
|
80
|
+
name: hoe
|
81
|
+
version_requirement:
|
82
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: 1.2.1
|
87
|
+
version:
|