table_fu 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/.gitignore +4 -0
  2. data/LICENSE +20 -0
  3. data/README +37 -0
  4. data/Rakefile +58 -0
  5. data/VERSION.yml +5 -0
  6. data/doc/TableFu/Datum.html +743 -0
  7. data/doc/TableFu/Formatting.html +469 -0
  8. data/doc/TableFu/Header.html +198 -0
  9. data/doc/TableFu/Row.html +508 -0
  10. data/doc/TableFu.html +1806 -0
  11. data/doc/_index.html +154 -0
  12. data/doc/class_list.html +36 -0
  13. data/doc/css/common.css +1 -0
  14. data/doc/css/full_list.css +50 -0
  15. data/doc/css/style.css +268 -0
  16. data/doc/file.README.html +89 -0
  17. data/doc/file_list.html +38 -0
  18. data/doc/frames.html +13 -0
  19. data/doc/index.html +89 -0
  20. data/doc/js/app.js +99 -0
  21. data/doc/js/full_list.js +106 -0
  22. data/doc/js/jquery.js +19 -0
  23. data/doc/method_list.html +363 -0
  24. data/doc/top-level-namespace.html +85 -0
  25. data/documentation/css/dawn.css +121 -0
  26. data/documentation/css/styles.css +63 -0
  27. data/documentation/images/proplogo.png +0 -0
  28. data/documentation/index.html.erb +148 -0
  29. data/examples/columns.rb +7 -0
  30. data/examples/columns_hidden.rb +5 -0
  31. data/examples/faceting.rb +2 -0
  32. data/examples/formatting_options.rb +6 -0
  33. data/examples/last_name.rb +4 -0
  34. data/examples/link.rb +11 -0
  35. data/examples/only.rb +6 -0
  36. data/examples/rails_helpers.rb +3 -0
  37. data/examples/sort_by_column.rb +11 -0
  38. data/examples/sort_by_number.rb +0 -0
  39. data/examples/totals.rb +2 -0
  40. data/examples/zap_joyce.rb +3 -0
  41. data/index.html +210 -0
  42. data/lib/table_fu/formatting.rb +52 -0
  43. data/lib/table_fu.rb +386 -0
  44. data/spec/assets/sample.csv +476 -0
  45. data/spec/assets/test.csv +8 -0
  46. data/spec/assets/test_macro.csv +8 -0
  47. data/spec/rcov.opts +2 -0
  48. data/spec/readme_example_spec.rb +39 -0
  49. data/spec/spec.opts +4 -0
  50. data/spec/spec_helper.rb +4 -0
  51. data/spec/table_fu_spec.rb +221 -0
  52. data/table_fu.gemspec +112 -0
  53. metadata +141 -0
@@ -0,0 +1,148 @@
1
+ <%
2
+ $:.unshift File.expand_path(File.dirname(__FILE__), "/../lib/table_fu")
3
+
4
+ require 'uv'
5
+ require 'FasterCSV'
6
+ require 'table_fu'
7
+
8
+ def code_for(file, output=true)
9
+ return '' unless File.exists?("examples/#{file}.rb")
10
+ file = File.open("examples/#{file}.rb").read
11
+ html = Uv.parse(file, "xhtml", "ruby", false, "dawn", false)
12
+ out = ''
13
+ if output
14
+ csv =<<-CSV
15
+ Author,Best Book,Number of Pages,Style
16
+ Samuel Beckett,Malone Muert,120,Modernism
17
+ James Joyce,Ulysses,644,Modernism
18
+ Nicholson Baker,Mezannine,150,Minimalism
19
+ Vladimir Sorokin,The Queue,263,Satire
20
+ CSV
21
+ if block_given?
22
+ out = yield instance_eval(file)
23
+ else
24
+ out = instance_eval(file).inspect
25
+ end
26
+ out = "<em>Returns:</em>" + Uv.parse(out, 'xhtml', 'ruby', false, 'dawn', false)
27
+ end
28
+ "#{html}#{out}"
29
+ end %>
30
+ <!DOCTYPE html>
31
+ <html>
32
+ <head>
33
+ <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
34
+ <title>TableFu</title>
35
+ <link rel="stylesheet" type="text/css" href="documentation/css/styles.css" />
36
+ <link rel="stylesheet" type="text/css" href="documentation/css/dawn.css" />
37
+ </head>
38
+
39
+ <body>
40
+ <a href="http://www.propublica.org" class="propublica">&nbsp;</a>
41
+ <h1>TableFu <small>&ndash; Version: <%=
42
+ config = YAML.load(File.read('VERSION.yml'))
43
+ "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
44
+ %></small></h1>
45
+
46
+ <p><a href="http://github.com/propublica/table-fu">TableFu</a> is a ruby gem for spreadsheet-style handling of arrays (e.g. filtering, formatting, and sorting by "column" or "row"). In addition, it has the ability to <a href="#facet">facet</a> &mdash; or group &mdash; rows according to cell value. It was developed as a backend for its companion project <a href="http://www.github.com/propublica/table-setter">TableSetter</a>.</p>
47
+ <p>For example, <strong>TableFu</strong> can consume a csv file and sort on a column:
48
+ <%= code_for "sort_by_column" do |ret|
49
+ ret.rows.inspect
50
+ end
51
+ %>
52
+ </p>
53
+ <h2><a id="toc">Table of Contents</a></h2>
54
+ <ul>
55
+ <li><a href="#installation">Installation</a></li>
56
+ <li><a href="#usage">Usage</a></li>
57
+ <li><a href="#macros">Macros / Formatting</a></li>
58
+ <li><a href="#faceting">Faceting</a></li>
59
+ <li><a href="#manipulation">Manipulation</a></li>
60
+ <li><a href="#links">Links</a></li>
61
+ <li><a href="#credits">Credits</a></li>
62
+ <li><a href="#license">License</a></li>
63
+ </ul>
64
+ <h2><a id="installation" href="#toc">Installation</a></h2>
65
+ <p><strong>TableFu</strong> is available as a rubygem:
66
+ <pre class="dawn">
67
+ gem install table_fu</pre>
68
+ or from the actual source:
69
+ <pre class="dawn">
70
+ git clone git://github.com/propublica/table-fu.git
71
+ cd table-fu
72
+ rake install</pre>
73
+ </p>
74
+ <h2><a id="usage" href="#toc">Usage</a></h2>
75
+ <p>
76
+ The <strong>TableFu</strong> constructor takes two arguments; a 2 dimensional array or csv (file object or string) and a hash of column options or a block. TableFu will assume that the first row of the array contains the column headers. The simple options are:</p>
77
+ <p><strong>sorted_by:</strong> the column to sort by, it defaults to no sorting at all.
78
+ <%= code_for "sort_by_column" do |ret|
79
+ ret.rows.inspect
80
+ end
81
+ %>
82
+ </p>
83
+ <p><strong>columns:</strong> the columns to include in the table, useful when reordering and filtering extraneous columns. If no arguments are provided, <strong>TableFu</strong> will include all columns by default.
84
+ <%= code_for "columns" %>
85
+ Note that the columns are still accessible directly even if they're not in the columns array.
86
+ <%= code_for "columns_hidden" %>
87
+ </p>
88
+
89
+ <h2><a id="macros" href="#toc">Macros / Formatting</a></h2>
90
+ <p><strong>TableFu</strong> allows you to format columns of cells through the use of macros. See <a href="http://github.com/propublica/table-fu/blob/master/lib/table_fu/formatting.rb"><strong>TableFu::Formatting</strong></a> for the predefined macros available. </p>
91
+ <p>The <strong>formatting</strong> attribute should be a hash of the form:
92
+ <%= code_for "formatting_options", false %>
93
+ which will call the macro on the column name with the arguments if specified.
94
+ </p>
95
+ <p>For example, you can use the <strong>last_name</strong> formatter to extract the last name of a cell containing a person's name:
96
+ <%= code_for "last_name" %>
97
+ </p>
98
+ <p>Or you can build a meta column from two others containing an html link like so:
99
+ <%= code_for "link" %>
100
+ </p>
101
+ <p>Of course, you can provide your own macros by patching <a href="http://github.com/propublica/table-fu/blob/master/lib/table_fu/formatting.rb">TableFu::Formatting</a>. <a href="http://www.github.com/propublica/table-setter">TableSetter</a> includes rails view helpers directly in <strong>TableFu::Formatting</strong>.
102
+ <%= code_for "rails_helpers", false %>
103
+ </p>
104
+
105
+ <h2><a id="faceting" href="#toc">Faceting</a></h2>
106
+ <p>Faceting provides a way to group rows together using a cell value they share in common. Calling <strong>TableFu#faceted_by</strong> returns an array of table fu instances each with a <strong>faceted_on</strong> attribute and with only the rows where that value appears.
107
+ </p>
108
+ <p>In this example there are 2 rows where "Modernism" appears in the style column, so calling <strong>faceted_on</strong> with the argument <strong>"Style"</strong> returns a <strong>TableFu</strong> instance with those rows grouped together:
109
+ <%= code_for "faceting" do |s|
110
+ s.map { |table|
111
+ "table.faceted_on => #{table.faceted_on}, table.rows => #{table.rows.inspect}\n"
112
+ }.join('')
113
+ end %>
114
+ </p>
115
+ <h2><a id="manipulation" href="#toc">Manipulation / Output</a></h2>
116
+ <h3>Deleting Rows</h3>
117
+ <p>In addition to hiding columns and faceting <strong>TableFu</strong> can delete rows from the csv. Let's get rid of James Joyce (no one ever finished <em>Ulysses</em> anyway):
118
+ <%= code_for "zap_joyce" do |s|
119
+ s.rows.inspect
120
+ end %>
121
+ The deleted rows are still available in <strong>@deleted_rows</strong> for later access:
122
+ <%= code_for "zap_joyce" do |s|
123
+ "table.deleted_rows => #{s.deleted_rows.inspect}"
124
+ end %>
125
+ </p>
126
+ <h3>Pagination</h3>
127
+ <p>If you want only a chunk of the data, say to paginate your table, you can call <strong>only!</strong> with the range of values you want to keep:
128
+ <%= code_for "only" %>
129
+ </p>
130
+ <h3>Sum</h3>
131
+ <p>TableFu can also sum a column of values:
132
+ <%= code_for "totals" %>
133
+ </p>
134
+ <h2><a id="links" href="#toc">Links</a></h2>
135
+ <ul>
136
+ <li><a href="http://github.com/propublica/table-setter">TableSetter</a><br>A Sinatra app that uses <strong>TableFu</strong> to render public Google Spreadsheets in custom HTML.</li>
137
+ <li><a href="http://github.com/propublica/table-setter-generator">TableSetter Generator</a><br>
138
+ A rails generator that allows you to create a rails app like TableSetter.
139
+ </li>
140
+ <li><a href="http://github.com/propublica/table-fu/issues">Issues</a><br>Post bug reports and feature requests here.</li>
141
+ <li><a href="doc/index.html">API Docs</a></li>
142
+ </ul>
143
+ <h2><a id="credits" href="#toc">Credits</a></h2>
144
+ <p><a href="http://github.com/thejefflarson">Jeff Larson</a> (Maintainer), <a href="http://github.com/brianboyer/">Brian Boyer</a>, <a href="http://github.com/kleinmatic">Scott Klein</a>, <a href="http://github.com/markpercival">Mark Percival</a>, and <a href="http://github.com/seebq">Charles Brian Quinn</a>.</p>
145
+ <h2><a id="license" href="#toc">License</a></h2>
146
+ <pre><%= File.open("LICENSE").read %></pre>
147
+ </body>
148
+ </html>
@@ -0,0 +1,7 @@
1
+ spreadsheet = TableFu.new(csv) do |s|
2
+ s.columns = ["Best Book", "Author"]
3
+ end
4
+
5
+ spreadsheet.columns.map do |column|
6
+ spreadsheet.rows[0].column_for(column).to_s
7
+ end
@@ -0,0 +1,5 @@
1
+ spreadsheet = TableFu.new(csv) do |s|
2
+ s.columns = ["Best Book", "Author"]
3
+ end
4
+
5
+ spreadsheet.rows[0].column_for('Style').to_s
@@ -0,0 +1,2 @@
1
+ spreadsheet = TableFu.new(csv)
2
+ spreadsheet.faceted_by "Style"
@@ -0,0 +1,6 @@
1
+ {"Column Name" => 'Formatting Method Name'}
2
+
3
+ # or
4
+
5
+ {"Meta Column Name" => {"method" => "Method Name", "arguments" => ['Column 1', 'Column 2' ... 'Column N']}}
6
+
@@ -0,0 +1,4 @@
1
+ spreadsheet = TableFu.new(csv) do |s|
2
+ s.formatting = {"Author" => 'last_name'}
3
+ end
4
+ spreadsheet.rows[0].column_for('Author').to_s
data/examples/link.rb ADDED
@@ -0,0 +1,11 @@
1
+ csv = <<-EOF
2
+ Website,URL
3
+ Propublica,http://www.propublica.org/
4
+ EOF
5
+
6
+ spreadsheet = TableFu.new(csv) do |s|
7
+ s.formatting = {"Link" => {'method' => 'link', 'arguments' => ['Website','URL']}}
8
+ s.columns = ["Link"]
9
+ end
10
+
11
+ spreadsheet.rows[0].column_for('Link').to_s
data/examples/only.rb ADDED
@@ -0,0 +1,6 @@
1
+ spreadsheet = TableFu.new(csv) do |s|
2
+ s.sorted_by = {'Style' => {"order" => 'ascending'}}
3
+ end
4
+
5
+ spreadsheet.only!(2..4)
6
+ spreadsheet.rows
@@ -0,0 +1,3 @@
1
+ class TableFu::Formatting
2
+ extend ActionView::Helpers::NumberHelper
3
+ end
@@ -0,0 +1,11 @@
1
+ csv =<<-CSV
2
+ Author,Best Book,Number of Pages,Style
3
+ Samuel Beckett,Malone Muert,120,Modernism
4
+ James Joyce,Ulysses,644,Modernism
5
+ Nicholson Baker,Mezannine,150,Minimalism
6
+ Vladimir Sorokin,The Queue,263,Satire
7
+ CSV
8
+
9
+ spreadsheet = TableFu.new(csv) do |s|
10
+ s.sorted_by = {'Best Book' => {'order' => 'ascending'}}
11
+ end
File without changes
@@ -0,0 +1,2 @@
1
+ spreadsheet = TableFu.new(csv)
2
+ spreadsheet.total_for('Number of Pages').to_s
@@ -0,0 +1,3 @@
1
+ spreadsheet = TableFu.new(csv) do |s|
2
+ s.delete_rows! [1]
3
+ end
data/index.html ADDED
@@ -0,0 +1,210 @@
1
+
2
+ <!DOCTYPE html>
3
+ <html>
4
+ <head>
5
+ <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
6
+ <title>TableFu</title>
7
+ <link rel="stylesheet" type="text/css" href="documentation/css/styles.css" />
8
+ <link rel="stylesheet" type="text/css" href="documentation/css/dawn.css" />
9
+ </head>
10
+
11
+ <body>
12
+ <a href="http://www.propublica.org" class="propublica">&nbsp;</a>
13
+ <h1>TableFu <small>&ndash; Version: 0.1.1</small></h1>
14
+
15
+ <p><a href="http://github.com/propublica/table-fu">TableFu</a> is a ruby gem for spreadsheet-style handling of arrays (e.g. filtering, formatting, and sorting by "column" or "row"). In addition, it has the ability to <a href="#facet">facet</a> &mdash; or group &mdash; rows according to cell value. It was developed as a backend for its companion project <a href="http://www.github.com/propublica/table-setter">TableSetter</a>.</p>
16
+ <p>For example, <strong>TableFu</strong> can consume a csv file and sort on a column:
17
+ <pre class="dawn">csv <span class="Keyword">=</span>&lt;&lt;-CSV
18
+ Author,Best Book,Number of Pages,Style
19
+ Samuel Beckett,Malone Muert,120,Modernism
20
+ James Joyce,Ulysses,644,Modernism
21
+ Nicholson Baker,Mezannine,150,Minimalism
22
+ Vladimir Sorokin,The Queue,263,Satire
23
+ CSV
24
+
25
+ spreadsheet <span class="Keyword">=</span> <span class="Support">TableFu</span><span class="PunctuationSeparator">.</span><span class="Entity">new</span>(csv) <span class="Keyword">do </span><span class="PunctuationSeparator">|</span><span class="Variable">s</span><span class="PunctuationSeparator">|</span>
26
+ s<span class="PunctuationSeparator">.</span><span class="Entity">sorted_by</span> <span class="Keyword">=</span> {'Best Book' <span class="PunctuationSeparator">=&gt;</span> {'order' <span class="PunctuationSeparator">=&gt;</span> 'ascending'}}
27
+ <span class="Keyword">end</span>
28
+ </pre><em>Returns:</em><pre class="dawn">[[&quot;Samuel Beckett&quot;<span class="PunctuationSeparator">,</span> &quot;Malone Muert&quot;<span class="PunctuationSeparator">,</span> &quot;120&quot;<span class="PunctuationSeparator">,</span> &quot;Modernism&quot;]<span class="PunctuationSeparator">,</span> [&quot;Nicholson Baker&quot;<span class="PunctuationSeparator">,</span> &quot;Mezannine&quot;<span class="PunctuationSeparator">,</span> &quot;150&quot;<span class="PunctuationSeparator">,</span> &quot;Minimalism&quot;]<span class="PunctuationSeparator">,</span> [&quot;Vladimir Sorokin&quot;<span class="PunctuationSeparator">,</span> &quot;The Queue&quot;<span class="PunctuationSeparator">,</span> &quot;263&quot;<span class="PunctuationSeparator">,</span> &quot;Satire&quot;]<span class="PunctuationSeparator">,</span> [&quot;James Joyce&quot;<span class="PunctuationSeparator">,</span> &quot;Ulysses&quot;<span class="PunctuationSeparator">,</span> &quot;644&quot;<span class="PunctuationSeparator">,</span> &quot;Modernism&quot;]]
29
+ </pre>
30
+ </p>
31
+ <h2><a id="toc">Table of Contents</a></h2>
32
+ <ul>
33
+ <li><a href="#installation">Installation</a></li>
34
+ <li><a href="#usage">Usage</a></li>
35
+ <li><a href="#macros">Macros / Formatting</a></li>
36
+ <li><a href="#faceting">Faceting</a></li>
37
+ <li><a href="#manipulation">Manipulation</a></li>
38
+ <li><a href="#links">Links</a></li>
39
+ <li><a href="#credits">Credits</a></li>
40
+ <li><a href="#license">License</a></li>
41
+ </ul>
42
+ <h2><a id="installation" href="#toc">Installation</a></h2>
43
+ <p><strong>TableFu</strong> is available as a rubygem:
44
+ <pre class="dawn">
45
+ gem install table_fu</pre>
46
+ or from the actual source:
47
+ <pre class="dawn">
48
+ git clone git://github.com/propublica/table-fu.git
49
+ cd table-fu
50
+ rake install</pre>
51
+ </p>
52
+ <h2><a id="usage" href="#toc">Usage</a></h2>
53
+ <p>
54
+ The <strong>TableFu</strong> constructor takes two arguments; a 2 dimensional array or csv (file object or string) and a hash of column options or a block. TableFu will assume that the first row of the array contains the column headers. The simple options are:</p>
55
+ <p><strong>sorted_by:</strong> the column to sort by, it defaults to no sorting at all.
56
+ <pre class="dawn">csv <span class="Keyword">=</span>&lt;&lt;-CSV
57
+ Author,Best Book,Number of Pages,Style
58
+ Samuel Beckett,Malone Muert,120,Modernism
59
+ James Joyce,Ulysses,644,Modernism
60
+ Nicholson Baker,Mezannine,150,Minimalism
61
+ Vladimir Sorokin,The Queue,263,Satire
62
+ CSV
63
+
64
+ spreadsheet <span class="Keyword">=</span> <span class="Support">TableFu</span><span class="PunctuationSeparator">.</span><span class="Entity">new</span>(csv) <span class="Keyword">do </span><span class="PunctuationSeparator">|</span><span class="Variable">s</span><span class="PunctuationSeparator">|</span>
65
+ s<span class="PunctuationSeparator">.</span><span class="Entity">sorted_by</span> <span class="Keyword">=</span> {'Best Book' <span class="PunctuationSeparator">=&gt;</span> {'order' <span class="PunctuationSeparator">=&gt;</span> 'ascending'}}
66
+ <span class="Keyword">end</span>
67
+ </pre><em>Returns:</em><pre class="dawn">[[&quot;Samuel Beckett&quot;<span class="PunctuationSeparator">,</span> &quot;Malone Muert&quot;<span class="PunctuationSeparator">,</span> &quot;120&quot;<span class="PunctuationSeparator">,</span> &quot;Modernism&quot;]<span class="PunctuationSeparator">,</span> [&quot;Nicholson Baker&quot;<span class="PunctuationSeparator">,</span> &quot;Mezannine&quot;<span class="PunctuationSeparator">,</span> &quot;150&quot;<span class="PunctuationSeparator">,</span> &quot;Minimalism&quot;]<span class="PunctuationSeparator">,</span> [&quot;Vladimir Sorokin&quot;<span class="PunctuationSeparator">,</span> &quot;The Queue&quot;<span class="PunctuationSeparator">,</span> &quot;263&quot;<span class="PunctuationSeparator">,</span> &quot;Satire&quot;]<span class="PunctuationSeparator">,</span> [&quot;James Joyce&quot;<span class="PunctuationSeparator">,</span> &quot;Ulysses&quot;<span class="PunctuationSeparator">,</span> &quot;644&quot;<span class="PunctuationSeparator">,</span> &quot;Modernism&quot;]]
68
+ </pre>
69
+ </p>
70
+ <p><strong>columns:</strong> the columns to include in the table, useful when reordering and filtering extraneous columns. If no arguments are provided, <strong>TableFu</strong> will include all columns by default.
71
+ <pre class="dawn">spreadsheet <span class="Keyword">=</span> <span class="Support">TableFu</span><span class="PunctuationSeparator">.</span><span class="Entity">new</span>(csv) <span class="Keyword">do </span><span class="PunctuationSeparator">|</span><span class="Variable">s</span><span class="PunctuationSeparator">|</span>
72
+ s<span class="PunctuationSeparator">.</span><span class="Entity">columns</span> <span class="Keyword">=</span> [&quot;Best Book&quot;<span class="PunctuationSeparator">,</span> &quot;Author&quot;]
73
+ <span class="Keyword">end</span>
74
+
75
+ spreadsheet<span class="PunctuationSeparator">.</span><span class="Entity">columns</span><span class="PunctuationSeparator">.</span><span class="Entity">map</span> <span class="Keyword">do </span><span class="PunctuationSeparator">|</span><span class="Variable">column</span><span class="PunctuationSeparator">|</span>
76
+ spreadsheet<span class="PunctuationSeparator">.</span><span class="Entity">rows</span>[<span class="Constant">0</span>]<span class="PunctuationSeparator">.</span><span class="Entity">column_for</span>(column)<span class="PunctuationSeparator">.</span><span class="Entity">to_s</span>
77
+ <span class="Keyword">end</span>
78
+ </pre><em>Returns:</em><pre class="dawn">[&quot;Malone Muert&quot;<span class="PunctuationSeparator">,</span> &quot;Samuel Beckett&quot;]
79
+ </pre>
80
+ Note that the columns are still accessible directly even if they're not in the columns array.
81
+ <pre class="dawn">spreadsheet <span class="Keyword">=</span> <span class="Support">TableFu</span><span class="PunctuationSeparator">.</span><span class="Entity">new</span>(csv) <span class="Keyword">do </span><span class="PunctuationSeparator">|</span><span class="Variable">s</span><span class="PunctuationSeparator">|</span>
82
+ s<span class="PunctuationSeparator">.</span><span class="Entity">columns</span> <span class="Keyword">=</span> [&quot;Best Book&quot;<span class="PunctuationSeparator">,</span> &quot;Author&quot;]
83
+ <span class="Keyword">end</span>
84
+
85
+ spreadsheet<span class="PunctuationSeparator">.</span><span class="Entity">rows</span>[<span class="Constant">0</span>]<span class="PunctuationSeparator">.</span><span class="Entity">column_for</span>('Style')<span class="PunctuationSeparator">.</span>to_s
86
+ </pre><em>Returns:</em><pre class="dawn">&quot;Modernism&quot;
87
+ </pre>
88
+ </p>
89
+
90
+ <h2><a id="macros" href="#toc">Macros / Formatting</a></h2>
91
+ <p><strong>TableFu</strong> allows you to format columns of cells through the use of macros. See <a href="http://github.com/propublica/table-fu/blob/master/lib/table_fu/formatting.rb"><strong>TableFu::Formatting</strong></a> for the predefined macros available. </p>
92
+ <p>The <strong>formatting</strong> attribute should be a hash of the form:
93
+ <pre class="dawn">{&quot;Column Name&quot; <span class="PunctuationSeparator">=&gt;</span> 'Formatting Method Name'}
94
+
95
+ <span class="Comment"><span class="Comment">#</span> or</span>
96
+
97
+ {&quot;Meta Column Name&quot; <span class="PunctuationSeparator">=&gt;</span> {&quot;method&quot; <span class="PunctuationSeparator">=&gt;</span> &quot;Method Name&quot;<span class="PunctuationSeparator">,</span> &quot;arguments&quot; <span class="PunctuationSeparator">=&gt;</span> ['Column 1'<span class="PunctuationSeparator">,</span> 'Column 2' <span class="PunctuationSeparator">.</span><span class="PunctuationSeparator">.</span><span class="PunctuationSeparator">.</span> 'Column N']}}
98
+
99
+ </pre>
100
+ which will call the macro on the column name with the arguments if specified.
101
+ </p>
102
+ <p>For example, you can use the <strong>last_name</strong> formatter to extract the last name of a cell containing a person's name:
103
+ <pre class="dawn">spreadsheet <span class="Keyword">=</span> <span class="Support">TableFu</span><span class="PunctuationSeparator">.</span><span class="Entity">new</span>(csv) <span class="Keyword">do </span><span class="PunctuationSeparator">|</span><span class="Variable">s</span><span class="PunctuationSeparator">|</span>
104
+ s<span class="PunctuationSeparator">.</span><span class="Entity">formatting</span> <span class="Keyword">=</span> {&quot;Author&quot; <span class="PunctuationSeparator">=&gt;</span> 'last_name'}
105
+ <span class="Keyword">end</span>
106
+ spreadsheet<span class="PunctuationSeparator">.</span><span class="Entity">rows</span>[<span class="Constant">0</span>]<span class="PunctuationSeparator">.</span><span class="Entity">column_for</span>('Author')<span class="PunctuationSeparator">.</span>to_s
107
+ </pre><em>Returns:</em><pre class="dawn">&quot;Beckett&quot;
108
+ </pre>
109
+ </p>
110
+ <p>Or you can build a meta column from two others containing an html link like so:
111
+ <pre class="dawn">csv <span class="Keyword">=</span> &lt;&lt;-EOF
112
+ Website,URL
113
+ Propublica,http://www.propublica.org/
114
+ EOF
115
+
116
+ spreadsheet <span class="Keyword">=</span> <span class="Support">TableFu</span><span class="PunctuationSeparator">.</span><span class="Entity">new</span>(csv) <span class="Keyword">do </span><span class="PunctuationSeparator">|</span><span class="Variable">s</span><span class="PunctuationSeparator">|</span>
117
+ s<span class="PunctuationSeparator">.</span><span class="Entity">formatting</span> <span class="Keyword">=</span> {&quot;Link&quot; <span class="PunctuationSeparator">=&gt;</span> {'method' <span class="PunctuationSeparator">=&gt;</span> 'link'<span class="PunctuationSeparator">,</span> 'arguments' <span class="PunctuationSeparator">=&gt;</span> ['Website'<span class="PunctuationSeparator">,</span>'URL']}}
118
+ s<span class="PunctuationSeparator">.</span><span class="Entity">columns</span> <span class="Keyword">=</span> [&quot;Link&quot;]
119
+ <span class="Keyword">end</span>
120
+
121
+ spreadsheet<span class="PunctuationSeparator">.</span><span class="Entity">rows</span>[<span class="Constant">0</span>]<span class="PunctuationSeparator">.</span><span class="Entity">column_for</span>('Link')<span class="PunctuationSeparator">.</span>to_s
122
+ </pre><em>Returns:</em><pre class="dawn">&quot;&lt;a href='http://www.propublica.org/' title='Propublica'&gt;Propublica&lt;/a&gt;&quot;
123
+ </pre>
124
+ </p>
125
+ <p>Of course, you can provide your own macros by patching <a href="http://github.com/propublica/table-fu/blob/master/lib/table_fu/formatting.rb">TableFu::Formatting</a>. <a href="http://www.github.com/propublica/table-setter">TableSetter</a> includes rails view helpers directly in <strong>TableFu::Formatting</strong>.
126
+ <pre class="dawn"><span class="Keyword">class</span> <span class="Entity">TableFu::Formatting</span>
127
+ <span class="Keyword">extend</span> <span class="Support">ActionView</span><span class="PunctuationSeparator">::</span><span class="Entity">Helpers</span><span class="PunctuationSeparator">::</span><span class="Entity">NumberHelper</span>
128
+ <span class="Keyword">end</span>
129
+ </pre>
130
+ </p>
131
+
132
+ <h2><a id="faceting" href="#toc">Faceting</a></h2>
133
+ <p>Faceting provides a way to group rows together using a cell value they share in common. Calling <strong>TableFu#faceted_by</strong> returns an array of table fu instances each with a <strong>faceted_on</strong> attribute and with only the rows where that value appears.
134
+ </p>
135
+ <p>In this example there are 2 rows where "Modernism" appears in the style column, so calling <strong>faceted_on</strong> with the argument <strong>"Style"</strong> returns a <strong>TableFu</strong> instance with those rows grouped together:
136
+ <pre class="dawn">spreadsheet <span class="Keyword">=</span> <span class="Support">TableFu</span><span class="PunctuationSeparator">.</span><span class="Entity">new</span>(csv)
137
+ spreadsheet<span class="PunctuationSeparator">.</span><span class="Entity">faceted_by</span> &quot;Style&quot;
138
+ </pre><em>Returns:</em><pre class="dawn">table<span class="PunctuationSeparator">.</span><span class="Entity">faceted_on</span> <span class="PunctuationSeparator">=&gt;</span> <span class="Variable">Minimalism</span><span class="PunctuationSeparator">,</span> table<span class="PunctuationSeparator">.</span><span class="Entity">rows</span> <span class="PunctuationSeparator">=&gt;</span> [[&quot;Nicholson Baker&quot;<span class="PunctuationSeparator">,</span> &quot;Mezannine&quot;<span class="PunctuationSeparator">,</span> &quot;150&quot;<span class="PunctuationSeparator">,</span> &quot;Minimalism&quot;]]
139
+ table<span class="PunctuationSeparator">.</span><span class="Entity">faceted_on</span> <span class="PunctuationSeparator">=&gt;</span> <span class="Variable">Modernism</span><span class="PunctuationSeparator">,</span> table<span class="PunctuationSeparator">.</span><span class="Entity">rows</span> <span class="PunctuationSeparator">=&gt;</span> [[&quot;Samuel Beckett&quot;<span class="PunctuationSeparator">,</span> &quot;Malone Muert&quot;<span class="PunctuationSeparator">,</span> &quot;120&quot;<span class="PunctuationSeparator">,</span> &quot;Modernism&quot;]<span class="PunctuationSeparator">,</span> [&quot;James Joyce&quot;<span class="PunctuationSeparator">,</span> &quot;Ulysses&quot;<span class="PunctuationSeparator">,</span> &quot;644&quot;<span class="PunctuationSeparator">,</span> &quot;Modernism&quot;]]
140
+ table<span class="PunctuationSeparator">.</span><span class="Entity">faceted_on</span> <span class="PunctuationSeparator">=&gt;</span> <span class="Variable">Satire</span><span class="PunctuationSeparator">,</span> table<span class="PunctuationSeparator">.</span><span class="Entity">rows</span> <span class="PunctuationSeparator">=&gt;</span> [[&quot;Vladimir Sorokin&quot;<span class="PunctuationSeparator">,</span> &quot;The Queue&quot;<span class="PunctuationSeparator">,</span> &quot;263&quot;<span class="PunctuationSeparator">,</span> &quot;Satire&quot;]]
141
+ </pre>
142
+ </p>
143
+ <h2><a id="manipulation" href="#toc">Manipulation / Output</a></h2>
144
+ <h3>Deleting Rows</h3>
145
+ <p>In addition to hiding columns and faceting <strong>TableFu</strong> can delete rows from the csv. Let's get rid of James Joyce (no one ever finished <em>Ulysses</em> anyway):
146
+ <pre class="dawn">spreadsheet <span class="Keyword">=</span> <span class="Support">TableFu</span><span class="PunctuationSeparator">.</span><span class="Entity">new</span>(csv) <span class="Keyword">do </span><span class="PunctuationSeparator">|</span><span class="Variable">s</span><span class="PunctuationSeparator">|</span>
147
+ s<span class="PunctuationSeparator">.</span><span class="Entity">delete_rows!</span> [<span class="Constant">1</span>]
148
+ <span class="Keyword">end</span>
149
+ </pre><em>Returns:</em><pre class="dawn">[[&quot;Samuel Beckett&quot;<span class="PunctuationSeparator">,</span> &quot;Malone Muert&quot;<span class="PunctuationSeparator">,</span> &quot;120&quot;<span class="PunctuationSeparator">,</span> &quot;Modernism&quot;]<span class="PunctuationSeparator">,</span> [&quot;Nicholson Baker&quot;<span class="PunctuationSeparator">,</span> &quot;Mezannine&quot;<span class="PunctuationSeparator">,</span> &quot;150&quot;<span class="PunctuationSeparator">,</span> &quot;Minimalism&quot;]<span class="PunctuationSeparator">,</span> [&quot;Vladimir Sorokin&quot;<span class="PunctuationSeparator">,</span> &quot;The Queue&quot;<span class="PunctuationSeparator">,</span> &quot;263&quot;<span class="PunctuationSeparator">,</span> &quot;Satire&quot;]]
150
+ </pre>
151
+ The deleted rows are still available in <strong>@deleted_rows</strong> for later access:
152
+ <pre class="dawn">spreadsheet <span class="Keyword">=</span> <span class="Support">TableFu</span><span class="PunctuationSeparator">.</span><span class="Entity">new</span>(csv) <span class="Keyword">do </span><span class="PunctuationSeparator">|</span><span class="Variable">s</span><span class="PunctuationSeparator">|</span>
153
+ s<span class="PunctuationSeparator">.</span><span class="Entity">delete_rows!</span> [<span class="Constant">1</span>]
154
+ <span class="Keyword">end</span>
155
+ </pre><em>Returns:</em><pre class="dawn">table<span class="PunctuationSeparator">.</span><span class="Entity">deleted_rows</span> <span class="PunctuationSeparator">=&gt;</span> [[&quot;James Joyce&quot;<span class="PunctuationSeparator">,</span> &quot;Ulysses&quot;<span class="PunctuationSeparator">,</span> &quot;644&quot;<span class="PunctuationSeparator">,</span> &quot;Modernism&quot;]]
156
+ </pre>
157
+ </p>
158
+ <h3>Pagination</h3>
159
+ <p>If you want only a chunk of the data, say to paginate your table, you can call <strong>only!</strong> with the range of values you want to keep:
160
+ <pre class="dawn">spreadsheet <span class="Keyword">=</span> <span class="Support">TableFu</span><span class="PunctuationSeparator">.</span><span class="Entity">new</span>(csv) <span class="Keyword">do </span><span class="PunctuationSeparator">|</span><span class="Variable">s</span><span class="PunctuationSeparator">|</span>
161
+ s<span class="PunctuationSeparator">.</span><span class="Entity">sorted_by</span> <span class="Keyword">=</span> {'Style' <span class="PunctuationSeparator">=&gt;</span> {&quot;order&quot; <span class="PunctuationSeparator">=&gt;</span> 'ascending'}}
162
+ <span class="Keyword">end</span>
163
+
164
+ spreadsheet<span class="PunctuationSeparator">.</span><span class="Entity">only!</span>(<span class="Constant">2</span><span class="PunctuationSeparator">.</span><span class="PunctuationSeparator">.</span><span class="Constant">4</span>)
165
+ spreadsheet<span class="PunctuationSeparator">.</span>rows
166
+ </pre><em>Returns:</em><pre class="dawn">[[&quot;Nicholson Baker&quot;<span class="PunctuationSeparator">,</span> &quot;Mezannine&quot;<span class="PunctuationSeparator">,</span> &quot;150&quot;<span class="PunctuationSeparator">,</span> &quot;Minimalism&quot;]<span class="PunctuationSeparator">,</span> [&quot;Vladimir Sorokin&quot;<span class="PunctuationSeparator">,</span> &quot;The Queue&quot;<span class="PunctuationSeparator">,</span> &quot;263&quot;<span class="PunctuationSeparator">,</span> &quot;Satire&quot;]]
167
+ </pre>
168
+ </p>
169
+ <h3>Sum</h3>
170
+ <p>TableFu can also sum a column of values:
171
+ <pre class="dawn">spreadsheet <span class="Keyword">=</span> <span class="Support">TableFu</span><span class="PunctuationSeparator">.</span><span class="Entity">new</span>(csv)
172
+ spreadsheet<span class="PunctuationSeparator">.</span><span class="Entity">total_for</span>('Number of Pages')<span class="PunctuationSeparator">.</span>to_s
173
+ </pre><em>Returns:</em><pre class="dawn"><span class="Constant">1177</span>
174
+ </pre>
175
+ </p>
176
+ <h2><a id="links" href="#toc">Links</a></h2>
177
+ <ul>
178
+ <li><a href="http://github.com/propublica/table-setter">TableSetter</a><br>A Sinatra app that uses <strong>TableFu</strong> to render public Google Spreadsheets in custom HTML.</li>
179
+ <li><a href="http://github.com/propublica/table-setter-generator">TableSetter Generator</a><br>
180
+ A rails generator that allows you to create a rails app like TableSetter.
181
+ </li>
182
+ <li><a href="http://github.com/propublica/table-fu/issues">Issues</a><br>Post bug reports and feature requests here.</li>
183
+ <li><a href="doc/index.html">API Docs</a></li>
184
+ </ul>
185
+ <h2><a id="credits" href="#toc">Credits</a></h2>
186
+ <p><a href="http://github.com/thejefflarson">Jeff Larson</a> (Maintainer), <a href="http://github.com/brianboyer/">Brian Boyer</a>, <a href="http://github.com/kleinmatic">Scott Klein</a>, <a href="http://github.com/markpercival">Mark Percival</a>, and <a href="http://github.com/seebq">Charles Brian Quinn</a>.</p>
187
+ <h2><a id="license" href="#toc">License</a></h2>
188
+ <pre>Copyright (c) 2010 ProPublica
189
+
190
+ Permission is hereby granted, free of charge, to any person obtaining
191
+ a copy of this software and associated documentation files (the
192
+ "Software"), to deal in the Software without restriction, including
193
+ without limitation the rights to use, copy, modify, merge, publish,
194
+ distribute, sublicense, and/or sell copies of the Software, and to
195
+ permit persons to whom the Software is furnished to do so, subject to
196
+ the following conditions:
197
+
198
+ The above copyright notice and this permission notice shall be
199
+ included in all copies or substantial portions of the Software.
200
+
201
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
202
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
203
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
204
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
205
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
206
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
207
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
208
+ </pre>
209
+ </body>
210
+ </html>
@@ -0,0 +1,52 @@
1
+ # Override this class to add more formatting methods
2
+ #
3
+ # Methods expect one or more arguments, which could be nil, and should return the appropriate
4
+ # formatting and style.
5
+ class TableFu::Formatting
6
+
7
+ class << self
8
+
9
+ # Returns a currency formatted number
10
+ def currency(num)
11
+ begin
12
+ parts = num.to_s.split('.')
13
+ parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1,")
14
+ "$#{parts.join('.')}"
15
+ rescue
16
+ num
17
+ end
18
+ end
19
+
20
+ # Returns the last name of a name
21
+ # => last_name("Jeff Larson")
22
+ # >> Larson
23
+ def last_name(name)
24
+ name.strip!
25
+ if name.match(/\s(\w+)$/)
26
+ $1
27
+ else
28
+ name
29
+ end
30
+ end
31
+ # Returns that last name first of a name
32
+ # => last_name_first_name("Jeff Larson")
33
+ # >> Larson, Jeff
34
+ def last_name_first_name(name)
35
+ last = last_name(name)
36
+ first = name.gsub(last, '').strip
37
+ "#{last}, #{first}"
38
+ end
39
+
40
+ # Returns an html link constructed from link, linkname
41
+ def link(linkname, href)
42
+ "<a href='#{href}' title='#{linkname}'>#{linkname}</a>"
43
+ end
44
+
45
+ # Returns an error message if the given formatter isn't available
46
+ def method_missing(method)
47
+ "#{method.to_s} not a valid formatter!"
48
+ end
49
+
50
+ end
51
+
52
+ end