table_fu 0.1.1

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.
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