Permalink
Browse files

Minor ruby style changes

  • Loading branch information...
1 parent c0cecbb commit bd7df13f44abb6ade02d4267f1b686083f372d5a @snusnu snusnu committed Apr 12, 2010
Showing with 52 additions and 47 deletions.
  1. +30 −32 lib/data_table.rb
  2. +22 −15 test/test_data_table.rb
View
@@ -1,16 +1,16 @@
require 'fastercsv'
class DataTable
+
class ColumnAlreadyExists < StandardError ; end
- class ColumnNotFound < StandardError ; end
+ class ColumnNotFound < StandardError ; end
- INFINITY = 1.0/0
+ INFINITY = 1.0 / 0
class Aggregators
- SUM = lambda do |key, rows|
- result = 0.0
- rows.each { |r| result += r[key] }
- result
+
+ SUM = lambda do |key, rows|
+ rows.inject(0.0) { |sum, row| sum += row[key] }
end
MIN = lambda do |key, rows|
@@ -24,26 +24,25 @@ class Aggregators
rows.each { |r| result = r[key] if r[key] > result }
result
end
+
end
class Column
- attr_accessor :key
- attr_accessor :header
- attr_accessor :transformer
+
+ attr_accessor :key, :header, :transformer
def initialize(key, header, transformer)
- @key = key
- @header = header
- @transformer = transformer
+ @key, @header, @transformer = key, header, transformer
end
+
end
class Row
+
attr_accessor :cells
def initialize(table)
- @table = table
- @cells = {}
+ @table, @cells = table, {}
end
# get cell
@@ -53,38 +52,38 @@ def [](key)
# set cell
def []=(key, value)
- raise ColumnNotFound unless @table.columns.has_key?(key)
+ raise ColumnNotFound unless @table.columns.key?(key)
@cells[key] = value
end
+
end
-
- attr_accessor :columns
- attr_accessor :rows
+
+
+ attr_accessor :rows, :columns
def initialize
- @columns = {}
- @column_keys = [] # used to memorize the order of columns
- @rows = []
+ @rows, @columns = [], {}
+ @column_keys = [] # used to memorize the order of columns
end
def add_column(key, header, transformer = nil)
- raise ColumnAlreadyExists if @columns.has_key?(key)
+ raise ColumnAlreadyExists if @columns.key?(key)
@column_keys << key
@columns[key] = Column.new(key, header, transformer)
end
def build_rows(items)
items.each do |item|
row = Row.new(self)
- @columns.each do |key, col|
+ columns.each do |key, col|
if col.transformer
row[key] = col.transformer.call(item)
elsif item.respond_to?(key)
row[key] = item.send(key)
end
end
yield(row, item) if block_given?
- @rows << row
+ rows << row
end
end
@@ -103,19 +102,19 @@ def aggregate(key, rows, aggregators, group_key)
# yields a grouped DataTable object
def group_by(key, aggregators, group_key = lambda {|x| x })
- result = DataTable.new
+ result = self.class.new
my_key = key
groups = {}
- @rows.each do |row|
+ rows.each do |row|
idx = group_key.call(row[key])
groups[idx] = groups[idx].to_a << row
end
# copy implicitly selected colums from original data table
- result.add_column(key, @columns[key].header)
+ result.add_column(key, columns[key].header)
aggregators.each_key do |key|
- result.add_column(key, @columns[key].header)
+ result.add_column(key, columns[key].header)
end
groups.each_value do |group|
@@ -130,13 +129,13 @@ def render_csv(options)
# Add headers
headers = []
@column_keys.each do |key|
- headers << @columns[key].header
+ headers << columns[key].header
end
csv << headers
# Add data rows
- @rows.each do |row|
+ rows.each do |row|
row_data = []
@column_keys.each do |key|
row_data << row[key]
@@ -146,6 +145,5 @@ def render_csv(options)
end
end
-end
-
+end
View
@@ -1,6 +1,7 @@
require 'helper'
class TestDataTable < Test::Unit::TestCase
+
context "A DataTable instance" do
setup do
@@ -29,36 +30,42 @@ def initialize(articlenum, name, group, ordered, quantity, price)
OrderPosition.new("DTJA6181", "R2DX", "BB", Date.new(2009, 10, 4), 1, 200.0 ),
OrderPosition.new("DTJA6181", "R2DX", "BB", Date.new(2009, 10, 4), 1, 20.0 )
]
+
end
should "work properly" do
t = DataTable.new
- # variant 1: implicit method lookup
- t.add_column(:articlenum, "Articlenum")
- t.add_column(:name, "Product Name")
- t.add_column(:ordered, "Datum")
- t.add_column(:group, "Product Group")
- # variant 2: explicit transformer function that yields an item of your collection
- t.add_column(:amount, "Amount", lambda { |p| p.quantity*p.price })
- # variant 3: explicit row modification (see build_rows!)
+ # Variant 1: implicit method lookup
+
+ t.add_column :articlenum, "Articlenum"
+ t.add_column :name, "Product Name"
+ t.add_column :ordered, "Datum"
+ t.add_column :group, "Product Group"
+
+ # Variant 2: explicit transformer function that yields an item of your collection
+
+ t.add_column(:amount, "Amount", lambda { |p| p.quantity*p.price })
+
+ # Variant 3: explicit row modification (see build_rows)
+
t.add_column(:doubled_price, "Doubled Price")
-
t.build_rows(@order_positions) do |row, p| # block can be omitted
- row[:doubled_price] = p.price*2
+ row[:doubled_price] = p.price * 2
end
-
+
+ # Grouping
+
grouped_table = t.group_by(:ordered, {
:amount => DataTable::Aggregators::SUM,
:doubled_price => DataTable::Aggregators::SUM
- }, lambda {|x| x.year.to_s+"-"+x.month.to_s})
-
+ }, lambda { |x| "#{x.year}-#{x.month}" })
+
# puts t.render_csv(:col_sep => ",")
puts grouped_table.render_csv(:col_sep => ",")
+
end
-
-
end
end

0 comments on commit bd7df13

Please sign in to comment.