tabular 0.0.7 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "ruby-ole", :git => "git://github.com/scottwillson/ruby-ole.git"
4
+ gem "spreadsheet", :git => "git://github.com/scottwillson/spreadsheet.git"
5
+ gem "jeweler"
data/Gemfile.lock ADDED
@@ -0,0 +1,34 @@
1
+ GIT
2
+ remote: git://github.com/scottwillson/ruby-ole.git
3
+ revision: 6b9d2530b12259ca21af75ed2dcb26ba745a6115
4
+ specs:
5
+ ruby-ole (1.2.11.3)
6
+
7
+ GIT
8
+ remote: git://github.com/scottwillson/spreadsheet.git
9
+ revision: e5d97bc43f3db66600a70ace5de638f41a4a700b
10
+ specs:
11
+ spreadsheet (0.6.6)
12
+ ruby-ole
13
+
14
+ GEM
15
+ remote: https://rubygems.org/
16
+ specs:
17
+ git (1.2.5)
18
+ jeweler (1.8.4)
19
+ bundler (~> 1.0)
20
+ git (>= 1.2.5)
21
+ rake
22
+ rdoc
23
+ json (1.7.7)
24
+ rake (10.0.4)
25
+ rdoc (4.0.1)
26
+ json (~> 1.4)
27
+
28
+ PLATFORMS
29
+ ruby
30
+
31
+ DEPENDENCIES
32
+ jeweler
33
+ ruby-ole!
34
+ spreadsheet!
data/Rakefile CHANGED
@@ -23,11 +23,9 @@ Rake::TestTask.new(:test) do |test|
23
23
  test.verbose = true
24
24
  end
25
25
 
26
- task :test => :check_dependencies
27
-
28
26
  task :default => :test
29
27
 
30
- require 'rake/rdoctask'
28
+ require 'rdoc/task'
31
29
  Rake::RDocTask.new do |rdoc|
32
30
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
33
31
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.7
1
+ 0.2.0
data/lib/tabular.rb CHANGED
@@ -2,9 +2,13 @@ require "rubygems"
2
2
 
3
3
  $LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib")
4
4
 
5
- require "tabular/column.rb"
6
- require "tabular/columns.rb"
7
- require "tabular/row.rb"
8
- require "tabular/table.rb"
5
+ require "tabular/keys"
6
+
7
+ require "tabular/column"
8
+ require "tabular/columns"
9
+ require "tabular/renderer"
10
+ require "tabular/row"
11
+ require "tabular/table"
9
12
 
10
13
  require "tabular/support/object"
14
+ require "tabular/support/zero"
@@ -1,12 +1,15 @@
1
1
  module Tabular
2
2
  class Column
3
3
  attr_reader :key, :column_type
4
-
5
- def initialize(key = nil, columns_map = {})
4
+
5
+ def initialize(table, columns, key = nil, columns_map = {})
6
+ @columns = columns
7
+ @table = table
8
+
6
9
  key = symbolize(key)
7
10
  columns_map = columns_map || {}
8
11
  map_for_key = columns_map[key]
9
-
12
+
10
13
  @column_type = :string
11
14
  case map_for_key
12
15
  when nil
@@ -17,7 +20,7 @@ module Tabular
17
20
  @column_type = :date if key == :date
18
21
  when Hash
19
22
  @key = key
20
- @column_type = map_for_key[:column_type]
23
+ @column_type = map_for_key[:column_type]
21
24
  else
22
25
  raise "Expected Symbol or Hash, but was #{map_for_key.class}"
23
26
  end
@@ -25,7 +28,7 @@ module Tabular
25
28
 
26
29
  def symbolize(key)
27
30
  return nil if key.blank?
28
-
31
+
29
32
  begin
30
33
  key.to_s.strip.gsub(/::/, '/').
31
34
  gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
@@ -38,13 +41,37 @@ module Tabular
38
41
  nil
39
42
  end
40
43
  end
41
-
44
+
45
+ def rows
46
+ @table.rows
47
+ end
48
+
49
+ def cells
50
+ rows.map { |r| r[key] }
51
+ end
52
+
53
+ def max
54
+ cells.compact.max
55
+ end
56
+
57
+ def precision
58
+ @precision || cells.map(&:to_f).map {|n| n.round(3) }.map {|n| n.to_s.split(".").last.gsub(/0+$/, "").length }.max
59
+ end
60
+
61
+ def render
62
+ renderer.render_header self
63
+ end
64
+
65
+ def renderer
66
+ @columns.renderer(key)
67
+ end
68
+
42
69
  def inspect
43
70
  "#<Tabular::Column #{key} #{column_type}>"
44
71
  end
45
-
72
+
46
73
  def to_s
47
- key
74
+ key.to_s
48
75
  end
49
76
  end
50
77
  end
@@ -2,18 +2,22 @@ module Tabular
2
2
  # The Table's header: a list of Columns.
3
3
  class Columns
4
4
  include Enumerable
5
-
5
+ include Tabular::Keys
6
+
7
+ attr_accessor :renderer
8
+
6
9
  # +data+ -- array of header names
7
10
  # +columns_map+ -- see Table. Maps column names and type conversion.
8
- def initialize(data, columns_map = {})
11
+ def initialize(table, names, columns_map = {})
12
+ @table = table
9
13
  columns_map ||= {}
10
14
  @columns_map = normalize_columns_map(columns_map)
11
15
  @column_indexes = {}
12
16
  @columns_by_key = {}
13
17
  index = 0
14
18
  @columns = nil
15
- @columns = data.map do |column|
16
- new_column = Tabular::Column.new(column, @columns_map)
19
+ @columns = names.map do |column|
20
+ new_column = Tabular::Column.new(table, self, column, @columns_map)
17
21
  unless new_column.key.blank?
18
22
  @column_indexes[new_column.key] = index
19
23
  @columns_by_key[new_column.key] = new_column
@@ -22,50 +26,76 @@ module Tabular
22
26
  new_column
23
27
  end
24
28
  end
25
-
29
+
26
30
  # Is the a Column with this key? Keys are lower-case, underscore symbols.
27
31
  # Example: :postal_code
28
32
  def has_key?(key)
29
33
  @columns.any? { |column| column.key == key }
30
34
  end
31
-
35
+
32
36
  # Column for +key+
33
37
  def [](key)
34
- @columns_by_key[key]
38
+ @columns_by_key[key_to_sym(key)]
35
39
  end
36
-
40
+
37
41
  # Zero-based index of Column for +key+
38
42
  def index(key)
39
43
  @column_indexes[key]
40
44
  end
41
-
45
+
42
46
  # Call +block+ for each Column
43
47
  def each(&block)
44
48
  @columns.each(&block)
45
49
  end
46
-
50
+
47
51
  # Add a new Column with +key+
48
52
  def <<(key)
49
- column = Column.new(key, @columns_map)
50
- unless column.key.blank?
53
+ column = Column.new(@table, self, key, @columns_map)
54
+ unless column.key.blank? || has_key?(key)
51
55
  @column_indexes[column.key] = @columns.size
52
56
  @column_indexes[@columns.size] = column
53
57
  @columns_by_key[column.key] = column
58
+ @columns << column
54
59
  end
55
- @columns << column
56
60
  end
57
-
58
-
59
- private
60
-
61
+
62
+ def delete(key)
63
+ @columns.delete_if { |column| column.key == key }
64
+ @columns_by_key.delete key
65
+ @column_indexes.delete key
66
+
67
+ @columns.each.with_index do |column, index|
68
+ @column_indexes[column.key] = index
69
+ end
70
+ end
71
+
72
+ def size
73
+ @columns.size
74
+ end
75
+
76
+ def max
77
+ cells.compact.max
78
+ end
79
+
80
+ def renderer(key)
81
+ renderers[key] || @renderer || Renderer
82
+ end
83
+
84
+ def renderers
85
+ @renderers ||= {}
86
+ end
87
+
88
+
89
+ private
90
+
61
91
  def normalize_columns_map(columns_map)
62
92
  normalized_columns_map = {}
63
93
  columns_map.each do |key, value|
64
94
  case value
65
95
  when Hash, Symbol
66
- normalized_columns_map[key.to_sym] = value
96
+ normalized_columns_map[key_to_sym(key)] = value
67
97
  else
68
- normalized_columns_map[key.to_sym] = value.to_sym
98
+ normalized_columns_map[key_to_sym(key)] = value.to_sym
69
99
  end
70
100
  end
71
101
  normalized_columns_map
@@ -0,0 +1,14 @@
1
+ module Tabular
2
+ module Keys
3
+ def key_to_sym(key)
4
+ _key = case key
5
+ when Column
6
+ key.key
7
+ when String
8
+ key.to_sym
9
+ else
10
+ key
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ module Tabular
2
+ class Renderer
3
+ def self.render(column, row)
4
+ row[column.key]
5
+ end
6
+
7
+ def self.render_header(column)
8
+ column.to_s
9
+ end
10
+ end
11
+ end
data/lib/tabular/row.rb CHANGED
@@ -4,23 +4,37 @@ module Tabular
4
4
  # Associate list of cells. Each Table has a list of Rows. Access Row cells via symbols. Ex: row[:city]
5
5
  class Row
6
6
  include Enumerable
7
-
7
+ include Tabular::Keys
8
+
8
9
  attr_reader :index
9
-
10
+ attr_reader :source
11
+
10
12
  # +table+ -- Table
11
- # +cell+ -- array (not neccessarily Strings)
12
- def initialize(table, cells = [])
13
+ # +cells+ -- array (not neccessarily Strings)
14
+ # +source+ -- original data before mapped to Hash or Array (optional)
15
+ def initialize(table, cells = [], source = nil)
13
16
  @table = table
14
- @array = cells
15
- @hash = nil
17
+ @source = source || cells
18
+
19
+ if cells.respond_to?(:keys)
20
+ @array = cells.values
21
+ @hash = {}
22
+ cells.each do |key, value|
23
+ @hash[key_to_sym(key)] = value
24
+ end
25
+ else
26
+ @array = cells
27
+ @hash = nil
28
+ end
29
+
16
30
  @index = table.rows.size
17
31
  end
18
-
32
+
19
33
  # Cell value by symbol. E.g., row[:phone_number]
20
34
  def [](key)
21
35
  hash[key]
22
36
  end
23
-
37
+
24
38
  # Set cell value. Adds cell to end of Row and adds new Column if there is no Column for +key_
25
39
  def []=(key, value)
26
40
  if columns.has_key?(key)
@@ -31,42 +45,61 @@ module Tabular
31
45
  end
32
46
  hash[key] = value
33
47
  end
34
-
48
+
35
49
  # Call +block+ for each cell
36
50
  def each(&block)
37
51
  @array.each(&block)
38
52
  end
39
53
 
54
+ # Call +block+ for each cell
55
+ def each_with_key(&block)
56
+ hash.each(&block)
57
+ end
58
+
59
+ def keys
60
+ hash.keys
61
+ end
62
+
40
63
  # For pretty-printing cell values
41
64
  def join(sep = nil)
42
65
  @array.join(sep)
43
66
  end
44
-
67
+
68
+ def delete(key)
69
+ @array.delete key
70
+ hash.delete key
71
+ end
72
+
45
73
  def previous
46
74
  if index > 0
47
75
  @table.rows[index - 1]
48
76
  end
49
77
  end
50
-
78
+
51
79
  def columns
52
80
  @table.columns
53
81
  end
54
-
82
+
83
+ def render(key)
84
+ column = columns[key]
85
+ column.renderer.render column, self
86
+ end
87
+
55
88
  def to_hash
56
89
  hash.dup
57
90
  end
58
-
91
+
59
92
  def inspect
60
93
  hash.inspect
61
94
  end
62
-
95
+
63
96
  def to_s
64
97
  @array.join(", ").to_s
65
98
  end
66
99
 
67
100
 
68
101
  protected
69
-
102
+
70
103
  def hash #:nodoc:
71
104
  unless @hash
72
105
  @hash = Hash.new
@@ -103,14 +136,14 @@ module Tabular
103
136
  end
104
137
  @hash
105
138
  end
106
-
107
-
139
+
140
+
108
141
  private
109
-
142
+
110
143
  # Handle common m/d/yy case that Date.parse dislikes
111
144
  def parse_invalid_date(value)
112
145
  return unless value
113
-
146
+
114
147
  parts = value.split("/")
115
148
  return unless parts.size == 3
116
149
 
@@ -128,7 +161,7 @@ module Tabular
128
161
  elsif year < 1900 || year > 2050
129
162
  return nil
130
163
  end
131
-
164
+
132
165
  Date.new(year, month, day)
133
166
  end
134
167
  end
@@ -0,0 +1,29 @@
1
+ class Object
2
+ def zero?
3
+ false
4
+ end
5
+ end
6
+
7
+ class NilClass #:nodoc:
8
+ def zero?
9
+ false
10
+ end
11
+ end
12
+
13
+ class FalseClass #:nodoc:
14
+ def zero?
15
+ false
16
+ end
17
+ end
18
+
19
+ class TrueClass #:nodoc:
20
+ def zero?
21
+ false
22
+ end
23
+ end
24
+
25
+ class String #:nodoc:
26
+ def zero?
27
+ self == "0" || self[/^0+\.0+$/]
28
+ end
29
+ end