Skip to content

Commit

Permalink
added subgroup headers and some examples
Browse files Browse the repository at this point in the history
  • Loading branch information
schacon committed Apr 18, 2008
1 parent 2c6bf2b commit 34bc04a
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 27 deletions.
30 changes: 30 additions & 0 deletions examples/column_add.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
require File.dirname(__FILE__) + "/example_helper"
include ExampleHelper

data = Munger::Data.load_data(test_data)

data.add_column([:advert, :rate]) do |row|
rate = (row.clicks / row.airtime)
[row.advert.capitalize, rate]
end

#data.filter_rows { |row| row.rate > 10 }

#new_columns = data.pivot('airtime', 'advert', 'rate', :average)

report = Munger::Report.from_data(data)
report.columns(:advert => 'Spot', :airdate => 'Air Date', :airtime => 'Airtime', :rate => 'Rate')
report.sort = [['airtime', :asc], ['rate', :asc]]
#report.subgroup('airtime')
#report.aggregate(Proc.new {|arr| arr.inject(0) {|total, i| i * i + (total - 30) }} => :airtime, :avg => :rate)
report.process

report.style_cells('myRed', :only => :rate) { |cell, row| (cell.to_i < 10) }

#puts html = Munger::Render.to_html(report, :classes => {:table => 'other-class'} )
puts text = Munger::Render.to_text(report)


f = File.open('test.html', 'w')
f.write(html)
f.close
2 changes: 2 additions & 0 deletions examples/development.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GET /example | Status: 200 | Params: {:format=>"html"}
GET /favicon.ico | Status: 404 | Params: {}
23 changes: 23 additions & 0 deletions examples/example_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require File.expand_path(File.dirname(__FILE__) + "/../lib/munger")

require 'fileutils'
require 'logger'
require 'pp'

module ExampleHelper
def test_data
[
{:advert => "spot 1", :airtime => 15, :airdate => "2008-01-01", :clicks => 301},
{:advert => "spot 1", :airtime => 30, :airdate => "2008-01-02", :clicks => 199},
{:advert => "spot 1", :airtime => 30, :airdate => "2008-01-03", :clicks => 234},
{:advert => "spot 1", :airtime => 15, :airdate => "2008-01-04", :clicks => 342},
{:advert => "spot 2", :airtime => 30, :airdate => "2008-01-01", :clicks => 172},
{:advert => "spot 2", :airtime => 15, :airdate => "2008-01-02", :clicks => 217},
{:advert => "spot 2", :airtime => 90, :airdate => "2008-01-03", :clicks => 1023},
{:advert => "spot 2", :airtime => 30, :airdate => "2008-01-04", :clicks => 321},
{:advert => "spot 3", :airtime => 60, :airdate => "2008-01-01", :clicks => 512},
{:advert => "spot 3", :airtime => 30, :airdate => "2008-01-02", :clicks => 813},
{:advert => "spot 3", :airtime => 15, :airdate => "2008-01-03", :clicks => 333},
]
end
end
96 changes: 96 additions & 0 deletions examples/sinatra.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
require 'rubygems'
require 'sinatra'
require File.expand_path(File.dirname(__FILE__) + "/../lib/munger")

get '/' do
report = Munger::Report.from_data(test_data).process
out = Munger::Render.to_html(report, :classes => {:table => 'other-class'} )
show(out)
end

get '/pivot' do
data = Munger::Data.load_data(test_data)

data.add_column([:advert, :rate]) do |row|
rate = (row.clicks / row.airtime)
[row.advert.capitalize, rate]
end

new_columns = data.pivot('airtime', 'advert', 'rate', :average)

report = Munger::Report.from_data(data)
report.columns([:advert] + new_columns)
report.process

report.style_cells('myRed', :only => new_columns) { |cell, row| (cell.to_i < 10 && cell.to_i > 0) }

out = Munger::Render.to_html(report, :classes => {:table => 'other-class'} )

show(out)
end

get '/example' do
data = Munger::Data.load_data(test_data)

data.add_column([:advert, :rate]) do |row|
rate = (row.clicks / row.airtime)
[row.advert.capitalize, rate]
end

#data.filter_rows { |row| row.rate > 10 }
#new_columns = data.pivot('airtime', 'advert', 'rate', :average)

report = Munger::Report.from_data(data)
report.columns(:advert => 'Spot', :airdate => 'Air Date', :airtime => 'Airtime', :rate => 'Rate')
report.sort = [['airtime', :asc], ['rate', :asc]]
report.subgroup('airtime', :with_titles => true)
report.aggregate(Proc.new {|arr| arr.inject(0) {|total, i| i * i + (total - 30) }} => :airtime, :average => :rate)
report.process

report.style_cells('myRed', :only => :rate) { |cell, row| (cell.to_i < 10) }

out = Munger::Render.to_html(report, :classes => {:table => 'other-class'} )

show(out)
end

def test_data
[
{:advert => "spot 1", :airtime => 15, :airdate => "2008-01-01", :clicks => 301},
{:advert => "spot 1", :airtime => 30, :airdate => "2008-01-02", :clicks => 199},
{:advert => "spot 1", :airtime => 30, :airdate => "2008-01-03", :clicks => 234},
{:advert => "spot 1", :airtime => 15, :airdate => "2008-01-04", :clicks => 342},
{:advert => "spot 2", :airtime => 30, :airdate => "2008-01-01", :clicks => 172},
{:advert => "spot 2", :airtime => 15, :airdate => "2008-01-02", :clicks => 217},
{:advert => "spot 2", :airtime => 90, :airdate => "2008-01-03", :clicks => 1023},
{:advert => "spot 2", :airtime => 30, :airdate => "2008-01-04", :clicks => 321},
{:advert => "spot 3", :airtime => 60, :airdate => "2008-01-01", :clicks => 512},
{:advert => "spot 3", :airtime => 30, :airdate => "2008-01-02", :clicks => 813},
{:advert => "spot 3", :airtime => 15, :airdate => "2008-01-03", :clicks => 333},
]
end

def show(data)
%Q(
<html>
<head>
<style>
.myRed { background: #e44; }
tr.group0 { background: #bbb;}
tr.group1 { background: #ddd;}
tr.groupHeader1 { background: #ccc;}
table tr td {padding: 0 15px;}
table tr th { background: #aaa; padding: 5px; }
body { font-family: verdana, "Lucida Grande", arial, helvetica, sans-serif;
color: #333; }
</style>
</head>
<body>
#{data}
</body>
</html>
)
end
Empty file added examples/test.html
Empty file.
25 changes: 17 additions & 8 deletions lib/munger/render/html.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,31 @@ def render
classes << 'group' + row[:meta][:group].to_s if row[:meta][:group]
classes << cycle('even', 'odd')
classes.compact!

if row[:meta][:group_header]
classes << 'groupHeader' + row[:meta][:group_header].to_s
end

row_attrib = {}
row_attrib = {:class => classes.join(' ')} if classes.size > 0

x.tr(row_attrib) do
@report.columns.each do |column|
if row[:meta][:group_header]
header = @report.column_title(row[:meta][:group_name]) + ' : ' + row[:meta][:group_value].to_s
x.td(:colspan => @report.columns.size) { x << header }
else
@report.columns.each do |column|

cell_attrib = {}
if cst = row[:meta][:cell_styles]
cst = Item.ensure(cst)
if cell_styles = cst[column]
cell_attrib = {:class => cell_styles.join(' ')}
cell_attrib = {}
if cst = row[:meta][:cell_styles]
cst = Item.ensure(cst)
if cell_styles = cst[column]
cell_attrib = {:class => cell_styles.join(' ')}
end
end
end

x.td(cell_attrib) { x << row[:data][column].to_s }
x.td(cell_attrib) { x << row[:data][column].to_s }
end
end
end
end
Expand Down
69 changes: 53 additions & 16 deletions lib/munger/report.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Munger

class Report

attr_writer :data, :sort, :columns, :subgroup, :aggregate
attr_writer :data, :sort, :columns, :subgroup, :subgroup_options, :aggregate
attr_accessor :column_titles
attr_reader :process_data, :grouping_level

Expand Down Expand Up @@ -66,9 +66,10 @@ def sort(values = nil)
end
end

def subgroup(values = nil)
def subgroup(values = nil, options = {})
if values
@subgroup = values
@subgroup_options = options
self
else
@subgroup
Expand Down Expand Up @@ -164,7 +165,7 @@ def to_s
def translate_native(array_of_hashes)
@process_data = []
array_of_hashes.each do |row|
@process_data << {:data => Item.ensure(row), :meta => {}}
@process_data << {:data => Item.ensure(row), :meta => {:data => true}}
end
end

Expand All @@ -175,16 +176,7 @@ def do_add_aggregate_rows
totals = {}

@process_data.each_with_index do |row, index|
if level = row[:meta][:group]
# write the totals and reset level
@aggregate.each do |type, columns|
Data.array(columns).each do |column|
data = totals[column][level]
@process_data[index][:data][column] = calculate_aggregate(type, data)
totals[column][level] = []
end
end
else
if row[:meta][:data]
@aggregate.each do |type, columns|
Data.array(columns).each do |column|
value = row[:data][column]
Expand All @@ -195,6 +187,15 @@ def do_add_aggregate_rows
end
end
end
elsif level = row[:meta][:group]
# write the totals and reset level
@aggregate.each do |type, columns|
Data.array(columns).each do |column|
data = totals[column][level]
@process_data[index][:data][column] = calculate_aggregate(type, data)
totals[column][level] = []
end
end
end
end

Expand Down Expand Up @@ -235,23 +236,59 @@ def do_add_groupings
current = {}
new_data = []

first_row = @process_data.first
sub.reverse.each do |group|
current[group] = first_row[:data][group]
end
prev_row = {:data => {}}

@process_data.each_with_index do |row, index|
new_data << row
# insert header title rows
next_row = @process_data[index + 1]

if next_row
level = @grouping_level

# insert header rows
sub.each do |group|
if (prev_row[:data][group] != current[group]) && current[group]
group_row = {:data => {}, :meta => {:group_header => level,
:group_name => group, :group_value => row[:data][group]}}
new_data << group_row
end
end

# insert current row
new_data << row

# insert footer rows
sub.reverse.each do |group|
if (next_row[:data][group] != current[group]) && current[group]
group_row = {:data => {}, :meta => {:group => level}}
group_row = {:data => {}, :meta => {:group => level, :group_name => group}}
new_data << group_row
end
current[group] = next_row[:data][group]
level -= 1
end

prev_row = row

else # last row
level = @grouping_level

# insert header rows
sub.each do |group|
if (prev_row[:data][group] != current[group]) && current[group]
group_row = {:data => {}, :meta => {:group_header => level,
:group_name => group, :group_value => row[:data][group]}}
new_data << group_row
end
end

new_data << row

sub.reverse.each do |group|
group_row = {:data => {}, :meta => {:group => level}}
group_row = {:data => {}, :meta => {:group => level, :group_name => group}}
new_data << group_row
level -= 1
end
Expand Down
10 changes: 8 additions & 2 deletions spec/spec_render_html.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,20 @@
html = Munger::Render::Html.new(@report).render
html.should match(/151/) # only in the aggregate group
html.should have_tag('tr.group0', :count => 1)
html.should have_tag('tr.group1', :count => 8)
html.should have_tag('tr.group1', :count => 9)
end

it "should render group headers" do
@report = @report.subgroup(:age, :with_headers => true).process
html = Munger::Render::Html.new(@report).render
html.should have_tag('tr.groupHeader1', :count => 9)
end

it "should render cell styles" do
@report.process.style_rows('over_thirty') { |row| row.age > 29 }

html = Munger::Render::Html.new(@report).render
html.should have_tag('tr.over_thirty')
html.should have_tag('tr.over_thirty', :count => 6)
end

it "should render row styles" do
Expand Down
8 changes: 7 additions & 1 deletion spec/spec_report.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,14 @@
@report.get_subgroup_rows.should have(6).items
end

it "should be able to add subgroup headers"
it "should be able to add subgroup headers" do
@report.sort('score').subgroup('score', :with_headers => true)
@report.aggregate(:sum => :score).process
puts Munger::Render.to_text(@report)
end

it "should add the grouping name on the group line somewhere"

it "should be able to subgroup in multiple dimensions"

it "should be able to aggregate columns into subgroup rows" do
Expand Down

0 comments on commit 34bc04a

Please sign in to comment.