jsanders-ruport 1.7.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 (76) hide show
  1. data/AUTHORS +48 -0
  2. data/LICENSE +59 -0
  3. data/README +114 -0
  4. data/Rakefile +93 -0
  5. data/examples/RWEmerson.jpg +0 -0
  6. data/examples/anon.rb +43 -0
  7. data/examples/btree/commaleon/commaleon.rb +263 -0
  8. data/examples/btree/commaleon/sample_data/ticket_count.csv +124 -0
  9. data/examples/btree/commaleon/sample_data/ticket_count2.csv +119 -0
  10. data/examples/centered_pdf_text_box.rb +83 -0
  11. data/examples/data/tattle.dump +82 -0
  12. data/examples/example.csv +3 -0
  13. data/examples/line_plotter.rb +61 -0
  14. data/examples/pdf_report_with_common_base.rb +72 -0
  15. data/examples/png_embed.rb +54 -0
  16. data/examples/roadmap.png +0 -0
  17. data/examples/row_renderer.rb +39 -0
  18. data/examples/simple_pdf_lines.rb +25 -0
  19. data/examples/simple_templating_example.rb +34 -0
  20. data/examples/tattle_ruby_version.rb +39 -0
  21. data/examples/tattle_rubygems_version.rb +37 -0
  22. data/examples/trac_ticket_status.rb +59 -0
  23. data/lib/ruport.rb +127 -0
  24. data/lib/ruport/controller.rb +616 -0
  25. data/lib/ruport/controller/grouping.rb +71 -0
  26. data/lib/ruport/controller/table.rb +54 -0
  27. data/lib/ruport/data.rb +4 -0
  28. data/lib/ruport/data/feeder.rb +111 -0
  29. data/lib/ruport/data/grouping.rb +399 -0
  30. data/lib/ruport/data/record.rb +297 -0
  31. data/lib/ruport/data/table.rb +950 -0
  32. data/lib/ruport/extensions.rb +4 -0
  33. data/lib/ruport/formatter.rb +254 -0
  34. data/lib/ruport/formatter/csv.rb +149 -0
  35. data/lib/ruport/formatter/html.rb +161 -0
  36. data/lib/ruport/formatter/pdf.rb +591 -0
  37. data/lib/ruport/formatter/template.rb +187 -0
  38. data/lib/ruport/formatter/text.rb +231 -0
  39. data/lib/uport.rb +1 -0
  40. data/test/controller_test.rb +743 -0
  41. data/test/csv_formatter_test.rb +164 -0
  42. data/test/data_feeder_test.rb +88 -0
  43. data/test/grouping_test.rb +410 -0
  44. data/test/helpers.rb +11 -0
  45. data/test/html_formatter_test.rb +201 -0
  46. data/test/pdf_formatter_test.rb +354 -0
  47. data/test/record_test.rb +332 -0
  48. data/test/samples/addressbook.csv +6 -0
  49. data/test/samples/data.csv +3 -0
  50. data/test/samples/data.tsv +3 -0
  51. data/test/samples/dates.csv +1409 -0
  52. data/test/samples/erb_test.sql +1 -0
  53. data/test/samples/query_test.sql +1 -0
  54. data/test/samples/ruport_test.sql +8 -0
  55. data/test/samples/test.sql +2 -0
  56. data/test/samples/test.yaml +3 -0
  57. data/test/samples/ticket_count.csv +124 -0
  58. data/test/table_pivot_test.rb +134 -0
  59. data/test/table_test.rb +838 -0
  60. data/test/template_test.rb +48 -0
  61. data/test/text_formatter_test.rb +258 -0
  62. data/util/bench/data/record/bench_as_vs_to.rb +18 -0
  63. data/util/bench/data/record/bench_constructor.rb +46 -0
  64. data/util/bench/data/record/bench_indexing.rb +65 -0
  65. data/util/bench/data/record/bench_reorder.rb +35 -0
  66. data/util/bench/data/record/bench_to_a.rb +19 -0
  67. data/util/bench/data/table/bench_column_manip.rb +103 -0
  68. data/util/bench/data/table/bench_dup.rb +24 -0
  69. data/util/bench/data/table/bench_init.rb +67 -0
  70. data/util/bench/data/table/bench_manip.rb +125 -0
  71. data/util/bench/formatter/bench_csv.rb +14 -0
  72. data/util/bench/formatter/bench_html.rb +14 -0
  73. data/util/bench/formatter/bench_pdf.rb +14 -0
  74. data/util/bench/formatter/bench_text.rb +14 -0
  75. data/util/bench/samples/tattle.csv +1237 -0
  76. metadata +176 -0
data/AUTHORS ADDED
@@ -0,0 +1,48 @@
1
+ = Developers
2
+
3
+ - {Gregory Brown}[mailto:gregory.t.brown@gmail.com]
4
+ - {Dudley Flanders}[mailto:dudley@misnomer.us]
5
+ - {James Healy}[mailto:jimmy@deefa.com]
6
+ - Dinko Mehinovic
7
+ - {Michael Milner}[mailto:mikem836@gmail.com]
8
+
9
+ = Contributors / People we've (legally) stolen from:
10
+
11
+ Iain Broadfoot:
12
+ - RuportDay 2006 Participant
13
+
14
+ Eric Pugh:
15
+ - RuportDay 2006 Participant
16
+
17
+ James Edward Gray II:
18
+ - Original inspiration via query.rb
19
+ - system_extensions.rb
20
+
21
+ Mathijs Mohlmann:
22
+ - Performance Enhancement
23
+ TextPlugin r264-r265
24
+ HTMLPlugin r266
25
+
26
+ Francis Hwang:
27
+ - SQLSplit
28
+
29
+ Simon Claret:
30
+ - Initial PDF table support (now deprecated)
31
+
32
+ Daniel Berger:
33
+ - we vendored and modified attempt.rb to support it directly in Report.
34
+ Original website: http://raa.ruby-lang.org/project/attempt/
35
+
36
+ Marshall T. Vandegrift:
37
+ - Fixed a bug in Record's struct-like accessors (method_missing)
38
+ - Provided performance enhancements and tests for query.rb
39
+ - Improved alignment for Text Tables.
40
+
41
+ Stefan Mahlitz:
42
+ - Table#sort_rows_by
43
+
44
+ Chris Carter
45
+ - Table#remove_columns (r440)
46
+
47
+ Dave Nelson
48
+ - Grouping#sigma (r1131)
data/LICENSE ADDED
@@ -0,0 +1,59 @@
1
+ Ruport is copyrighted free software originally produced by Gregory Brown
2
+ <gregory.t.brown@gmail.com> which now contains a number of community
3
+ contributions and is actively developed by Michael Milner <mikem836@gmail.com>.
4
+
5
+ See the AUTHORS file for a complete list of contributors.
6
+
7
+ Licensing terms follow (License of Ruby 1.8):
8
+
9
+ You can redistribute Ruport and/or modify it under either the terms of the GPL
10
+ (see COPYING file), or the conditions below:
11
+
12
+ 1. You may make and give away verbatim copies of the source form of the
13
+ software without restriction, provided that you duplicate all of the
14
+ original copyright notices and associated disclaimers.
15
+
16
+ 2. You may modify your copy of the software in any way, provided that
17
+ you do at least ONE of the following:
18
+
19
+ a) place your modifications in the Public Domain or otherwise
20
+ make them Freely Available, such as by posting said
21
+ modifications to Usenet or an equivalent medium, or by allowing
22
+ the author to include your modifications in the software.
23
+
24
+ b) use the modified software only within your corporation or
25
+ organization.
26
+
27
+ c) rename any non-standard executables so the names do not conflict
28
+ with standard executables, which must also be provided.
29
+
30
+ d) make other distribution arrangements with the author.
31
+
32
+ 3. You may distribute the software in object code or executable
33
+ form, provided that you do at least ONE of the following:
34
+
35
+ a) distribute the executables and library files of the software,
36
+ together with instructions (in the manual page or equivalent)
37
+ on where to get the original distribution.
38
+
39
+ b) accompany the distribution with the machine-readable source of
40
+ the software.
41
+
42
+ c) give non-standard executables non-standard names, with
43
+ instructions on where to get the original software distribution.
44
+
45
+ d) make other distribution arrangements with the author.
46
+
47
+ 4. You may modify and include the part of the software into any other
48
+ software (possibly commercial).
49
+
50
+ 5. The scripts and library files supplied as input to or produced as
51
+ output from the software do not automatically fall under the
52
+ copyright of the software, but belong to whomever generated them,
53
+ and may be sold commercially, and may be aggregated with this
54
+ software.
55
+
56
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
57
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
58
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
59
+ PURPOSE.
data/README ADDED
@@ -0,0 +1,114 @@
1
+ # -----------------------------------------------------------------
2
+ # Contents:
3
+ #
4
+ # + What Ruport Is
5
+ # + Installation
6
+ # + Resources
7
+ # + Hacking
8
+ #
9
+ # = What Ruport Is
10
+ #
11
+ # Ruby Reports (Ruport) is an extensible reporting system.
12
+ #
13
+ # It aims to be as lightweight as possible while still providing core support
14
+ # for data aggregation and manipulation as well as multi-format rendering
15
+ # of reports.
16
+ #
17
+ # Ruport provides tools for using a number of data sources, including CSV files,
18
+ # ActiveRecord models, and raw SQL connections via RubyDBI (through ruport-util).
19
+ #
20
+ # Data manipulation is easy as there are standard structures that support
21
+ # record, table, and grouping operations. These all can be extended to
22
+ # implement custom behavior as needed.
23
+ #
24
+ # For common tasks, Ruport provides formatters for CSV, HTML, PDF, and text-
25
+ # based reports. However, the real power lies in building custom report
26
+ # controllers and formatters. The base formatting libraries provide a number
27
+ # of helper functions that will let you build complex reports while maintaining
28
+ # a DRY and consistent interface.
29
+ #
30
+ # To get a quick feel for what you can accomplish with Ruport, take a look at
31
+ # a few simple examples provided on our web site.
32
+ #
33
+ # http://rubyreports.org/examples.html
34
+ #
35
+ # Since Ruport's core support is intentionally minimalistic, you may be looking
36
+ # for some higher level support for specific needs such as graphing, invoices,
37
+ # report mailing support, etc. For this, you may wish to take a look at the
38
+ # ruport-util package, which contains some generally useful tools and libraries
39
+ # to extend Ruport's capabilities.
40
+ #
41
+ # = Installation
42
+ #
43
+ # To install ruport via rubygems:
44
+ #
45
+ # sudo gem install ruport
46
+ #
47
+ # Check to see if it installed properly:
48
+ #
49
+ # ruby -rubygems -e "require 'ruport'; puts Ruport::VERSION"
50
+ #
51
+ # If you get an error, please let us know on our mailing list.
52
+ #
53
+ # Dependencies Details:
54
+ #
55
+ # -- formatting
56
+ #
57
+ # Ruport relies on PDF::Writer and FasterCSV for its formatting support.
58
+ # If you want to make use of textile helpers, you'll also need RedCloth.
59
+ #
60
+ # -- database interaction
61
+ #
62
+ # If you wish to use Ruport to report against a rails project,
63
+ # a camping project, or do standalone acts_as_reportable reports, you'll need
64
+ # ActiveRecord and the acts_as_reportable gem.
65
+ #
66
+ # If you want to use Ruport::Query for raw SQL support, you'll need to
67
+ # install ruport-util, RubyDBI and whatever database drivers you might need.
68
+ #
69
+ # = Resources
70
+ #
71
+ # Our developers have published a free-content book about all things
72
+ # Ruport, including complete coverage of acts_as_reportable and some of
73
+ # ruport-util's features. This book serves as the definitive guide to
74
+ # Ruport, so all users should become acquainted with it:
75
+ #
76
+ # http://ruportbook.com
77
+ #
78
+ # The next best way to get help and make suggestions is the Ruport mailing list.
79
+ # This software is on the move, so the list is the most reliable way of getting
80
+ # up to date information.
81
+ #
82
+ # - You can sign up and/or view the archives here:
83
+ # http://groups.google.com/group/ruby-reports
84
+ #
85
+ # If you are looking to dig a little deeper, there are a couple more resources
86
+ # that may be helpful to you.
87
+ #
88
+ # - The latest stable API documentation is available at:
89
+ # http://api.rubyreports.org
90
+ #
91
+ # - Our Trac is at: http://code.rubyreports.org/ruport
92
+ # You may use the username ruport and password blinky to file tickets.
93
+ #
94
+ # = Hacking
95
+ #
96
+ # If you'd like to contribute code to Ruport, please join our development
97
+ # mailing list, and let us know what you'd like to do!
98
+ #
99
+ # http://groups.google.com/group/ruport-dev
100
+ #
101
+ # It also may be worthwhile to join this list if you plan on running edge
102
+ # versions of Ruport, as this is where we make announcements about major
103
+ # breakage in trunk.
104
+ #
105
+ # We are very responsive to contributors, and review every patch we receive
106
+ # fairly quickly. Most contributors who successfully get a patch or two applied
107
+ # are given write access to the repositories and invited to join Ruport's
108
+ # development team. Since we view every user as potential contributor, this
109
+ # approach works well for us.
110
+ #
111
+ # So if you want to help out with Ruport, we'll happy accept your efforts!
112
+
113
+
114
+
data/Rakefile ADDED
@@ -0,0 +1,93 @@
1
+ require "rake/rdoctask"
2
+ require "rake/testtask"
3
+
4
+ RUPORT_VERSION = "1.7.0"
5
+
6
+ begin
7
+ require "rubygems"
8
+ rescue LoadError
9
+ nil
10
+ end
11
+
12
+ task :default => [:test]
13
+
14
+ Rake::TestTask.new do |test|
15
+ test.libs << "test"
16
+ test.test_files = Dir[ "test/*_test.rb" ]
17
+ test.verbose = true
18
+ end
19
+
20
+ Rake::RDocTask.new do |rdoc|
21
+ rdoc.rdoc_files.include( "README",
22
+ #"CHANGELOG",
23
+ "AUTHORS", "COPYING",
24
+ "LICENSE", "lib/" )
25
+ rdoc.main = "README"
26
+ rdoc.rdoc_dir = "doc/html"
27
+ rdoc.title = "Ruport Documentation"
28
+ end
29
+
30
+ task :build_archives => [:package,:rcov,:rdoc] do
31
+ mv "pkg/ruport-#{RUPORT_VERSION}.tgz", "pkg/ruport-#{RUPORT_VERSION}.tar.gz"
32
+ sh "tar cjvf pkg/ruport_coverage-#{RUPORT_VERSION}.tar.bz2 coverage"
33
+ sh "tar cjvf pkg/ruport_doc-#{RUPORT_VERSION}.tar.bz2 doc/html"
34
+ cd "pkg"
35
+ sh "tar cjvf ruport-#{RUPORT_VERSION}.tar.bz2 ruport-#{RUPORT_VERSION}"
36
+ end
37
+
38
+ task :run_benchmarks do
39
+ files = FileList["util/bench/**/**/*.rb"]
40
+ files.sort!
41
+ files.uniq!
42
+ names = files.map { |r| r.sub("util/bench","").split("/").map { |e| e.capitalize } }
43
+ names.map! { |e| e[1..-2].join("::") + " <BENCH: #{e[-1].sub('Bench_','').sub('.rb','')}>" }
44
+ start_time = Time.now
45
+ files.zip(names).each { |f,n|
46
+ puts "\n#{n}\n\n"
47
+ sh "ruby -Ilib #{f}"
48
+ puts "\n"
49
+ }
50
+ end_time = Time.now
51
+ puts "\n** Total Run Time: #{end_time-start_time}s **"
52
+ end
53
+
54
+ begin
55
+ require 'rcov/rcovtask'
56
+ Rcov::RcovTask.new do |t|
57
+ t.test_files = Dir[ "test/*_test.rb" ]
58
+ end
59
+ rescue LoadError
60
+ nil
61
+ end
62
+
63
+ begin
64
+ require 'jeweler'
65
+ Jeweler::Tasks.new do |s|
66
+ s.name = "ruport"
67
+ s.version = RUPORT_VERSION
68
+ s.platform = Gem::Platform::RUBY
69
+ s.summary = "A generalized Ruby report generation and templating engine."
70
+ s.files = Dir.glob("{examples,lib,test,bin,util/bench}/**/**/*") +
71
+ ["Rakefile"]
72
+ s.require_path = "lib"
73
+
74
+ s.test_files = Dir[ "test/*_test.rb" ]
75
+ s.has_rdoc = true
76
+ s.extra_rdoc_files = %w{README LICENSE AUTHORS}
77
+ s.rdoc_options << '--title' << 'Ruport Documentation' <<
78
+ '--main' << 'README' << '-q'
79
+ s.add_dependency('fastercsv')
80
+ s.add_dependency('pdf-writer','= 1.1.8')
81
+ s.author = "Gregory Brown"
82
+ s.email = " gregory.t.brown@gmail.com"
83
+ s.rubyforge_project = "ruport"
84
+ s.homepage = "http://rubyreports.org"
85
+ s.description = <<-END_DESC
86
+ Ruby Reports is a software library that aims to make the task of reporting
87
+ less tedious and painful. It provides tools for data acquisition,
88
+ database interaction, formatting, and parsing/munging.
89
+ END_DESC
90
+ end
91
+ rescue LoadError
92
+ puts 'Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com'
93
+ end
Binary file
data/examples/anon.rb ADDED
@@ -0,0 +1,43 @@
1
+ # Demonstrates building a parent controller which provides additional 'built in'
2
+ # formats, allowing anonymous formatter support to use the simple interface
3
+ # rather than the :format => FormatterClass approach.
4
+
5
+ require "ruport"
6
+ module FooCorp
7
+ class Controller < Ruport::Controller
8
+ def self.built_in_formats
9
+ super.merge(:xml => FooCorp::Formatter::XML)
10
+ end
11
+ end
12
+
13
+ class Formatter
14
+ class XML < Ruport::Formatter
15
+
16
+ def xmlify(stuff)
17
+ output << "Wouldn't you like to see #{stuff} in XML?"
18
+ end
19
+ end
20
+ end
21
+
22
+ class MyController < FooCorp::Controller
23
+ stage :foo
24
+
25
+ formatter :xml do
26
+ build :foo do
27
+ xmlify "Red Snapper"
28
+ end
29
+ end
30
+
31
+ formatter :text do
32
+ build :foo do
33
+ output << "Red Snapper"
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ puts "XML:"
40
+ puts FooCorp::MyController.render_xml
41
+
42
+ puts "Text:"
43
+ puts FooCorp::MyController.render_text
@@ -0,0 +1,263 @@
1
+ # This example is a simplified version of a tool actually used at BTree.
2
+ # It does a very basic task:
3
+ #
4
+ # Given a master CSV file and a key column, it will compare the file
5
+ # to another CSV, and report back what is missing in the second CSV
6
+ # that was in the first, as well as what is changed in the second CSV
7
+ # based on the first.
8
+ #
9
+ # It is not bidirectional, and is mostly meant to compare snapshots
10
+ # of CSV dumps to see what has been removed or altered (we don't care
11
+ # about new records )
12
+ #
13
+ # It's a camping app, but the core of it is a controller/formatter combo.
14
+ # (Marked by %%%%%%%%%%% below)
15
+ #
16
+ # You'll need the camping omnibus and the F() ruport plugin to run this app.
17
+ #
18
+ # gem install camping-omnibus --source http://code.whytheluckystiff.net -y
19
+ # gem install f --source http://gems.rubyreports.org
20
+ #
21
+ # Once you have them, just run camping commaleon.rb and browse to
22
+ # http://localhost:3301
23
+ #
24
+ # Use ticket_count.csv as your master file and ticket_count2.csv as your
25
+ # comparison file. Use title as your key.
26
+ #
27
+ # Try out the different outputs, and tweak the app if you'd like to play
28
+ # with it.
29
+ #
30
+ # If your company has a need for tiny hackish camping/ruport amalgams,
31
+ # you can always ask Gregory if he's looking for work:
32
+ # <gregory.t.brown at gmail.com>
33
+ #
34
+ require "rubygems"
35
+ require "camping"
36
+ require "camping/session"
37
+ require "ruport"
38
+ require "ruport/extensions"
39
+
40
+ Camping.goes :Commaleon
41
+
42
+ module Commaleon
43
+ include Camping::Session
44
+ end
45
+
46
+ def Commaleon.create
47
+ Camping::Models::Session.create_schema
48
+ end
49
+
50
+ module Commaleon::Helpers
51
+
52
+ # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53
+ # This is the bulk of the Ruport code in this app
54
+ # (CSVDiffController and CSVDiffFormatter)
55
+ # The rest is just camping. The interesting thing here is that
56
+ # you could easily define these in another file and just require
57
+ # them here, and use them standalone outside of your web app.
58
+ # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
59
+
60
+ class CSVDiffController < Ruport::Controller
61
+ stage :diff_report
62
+ option :key, :mcsv, :ccsv
63
+
64
+ # This setup() idiom has become the default way of doing some
65
+ # manipulations on the data and options before handing off the
66
+ # rendering task to the formatters.
67
+ #
68
+ # We're using grouping mainly for the controller support,
69
+ # and rather than reducing a table, we're building up the
70
+ # group objects via the helper methods missing_from_compare
71
+ # and different_from_compare
72
+ def setup
73
+ @master_table = Table(:string => mcsv)
74
+ @compare_table = Table(:string => ccsv)
75
+ options.diff_report = Grouping(:by => "issue")
76
+ options.diff_report << missing_from_compare
77
+ options.diff_report << different_from_compare
78
+ end
79
+
80
+ # pulls the rows that are present in the master csv but not
81
+ # in the comparison csv and returns a group.
82
+ def missing_from_compare
83
+ missing_data = @master_table.rows_with(key) do |k|
84
+ missing_keys.include?(k)
85
+ end
86
+
87
+ Group("missing from main csv",
88
+ :data => missing_data,
89
+ :column_names => @master_table.column_names )
90
+ end
91
+
92
+ # pulls the rows that are present in the master csv but match
93
+ # a row with the same key in the compare csv that do not have
94
+ # identical attributes. Returns a group
95
+ def different_from_compare
96
+ shared = master_keys & compare_keys
97
+ m = @master_table.rows_with(key) do |k|
98
+ shared.include?(k)
99
+ end
100
+
101
+ diff = m.reject do |r|
102
+ @compare_table.any? { |s| s == r }
103
+ end
104
+
105
+ diff.each do |r|
106
+ comp = @compare_table.rows_with(key => r[key])[0]
107
+ r.to_hash.each do |k,v|
108
+ v << " ## " << comp[k] unless v == comp[k]
109
+ end
110
+ end
111
+
112
+ Group("different from main csv",
113
+ :data => diff, :column_names => @master_table.column_names)
114
+ end
115
+
116
+ def missing_keys
117
+ master_keys - compare_keys
118
+ end
119
+
120
+ def master_keys
121
+ @master_table.column(key)
122
+ end
123
+
124
+ def compare_keys
125
+ @compare_table.column(key)
126
+ end
127
+ end
128
+
129
+ # This is using the F plugin which saves us a line of code and just
130
+ # looks neat, IMO
131
+ #
132
+ # For more details:
133
+ #
134
+ # http://stonecode.svnrepository.com/ruport/trac.cgi/wiki/F
135
+ #
136
+ class CSVDiffFormatter < F([:html,:text,:csv,:pdf], :for => CSVDiffController)
137
+ def build_diff_report
138
+ # this is using the selective blocks for formatters that implement
139
+ # more than one format. The block below will only be called when this
140
+ # formatter is rendering HTML
141
+ html { gussy_up_html }
142
+
143
+ render_grouping( options.diff_report,
144
+ :style => options.style || :inline )
145
+ end
146
+
147
+ # adds headers to group name to make the output a little prettier
148
+ def gussy_up_html
149
+ options.diff_report.each do |n,g|
150
+ g.send(:name=, "<h4>#{n}</h4>")
151
+ end
152
+ end
153
+ end
154
+
155
+ end
156
+
157
+ module Commaleon::Controllers
158
+
159
+ class Index < R "/"
160
+ def get
161
+ redirect R(CSVDifference)
162
+ end
163
+ end
164
+
165
+ class CSVDifference < R '/csv_diff'
166
+ def get
167
+ render :get_diff_files
168
+ end
169
+
170
+ def post
171
+ @state.mfile = @input.mfile.tempfile.read
172
+ @state.cfile = @input.cfile.tempfile.read
173
+ redirect R(GenerateDiffReport)
174
+ end
175
+ end
176
+
177
+ class GenerateDiffReport < R '/csv_diff/report'
178
+ def get
179
+ @id_fields = Table(:string=>@state.mfile).column_names &
180
+ Table(:string=>@state.cfile).column_names
181
+ render :csv_get_id
182
+ end
183
+
184
+ def post
185
+ @state.key = @input.csv_id
186
+ @table = CSVDiffController.render_html(:key => @state.key,
187
+ :mcsv => @state.mfile,
188
+ :ccsv => @state.cfile )
189
+ render :html_diff
190
+ end
191
+ end
192
+
193
+ class CSVDiffReportFormatted < R '/csv_diff/report.(.*)'
194
+ def set_headers(format)
195
+ types = { "csv" => "application/vnd.ms-excel",
196
+ "pdf" => "application/pdf",
197
+ "txt" => "text/plain" }
198
+ @headers["Content-Type"] = types[format]
199
+ @headers["Content-Disposition"] = "attachment; filename=diff.#{format}"
200
+ end
201
+
202
+ def get(format)
203
+ options = { :key => @state.key,
204
+ :mcsv => @state.mfile,
205
+ :ccsv => @state.cfile }
206
+
207
+ set_headers(format)
208
+ case(format)
209
+ when "csv"
210
+ text CSVDiffController.render_csv(options)
211
+ when "pdf"
212
+ text CSVDiffController.render_pdf(options.merge(:style => :justified))
213
+ when "txt"
214
+ text CSVDiffController.render_text(options)
215
+ else
216
+ text "no format!"
217
+ end
218
+ end
219
+ end
220
+
221
+ end
222
+
223
+ module Commaleon::Views
224
+ def get_diff_files
225
+ form :action => "?upload_id=#{Time.now.to_f}", :method => 'post',
226
+ :enctype => 'multipart/form-data' do
227
+ p do
228
+ label "Master File: ", :for => "mfile"
229
+ input({:name => "mfile", :type => 'file'})
230
+ end
231
+ p do
232
+ label "Comparison File: ", :for => "cfile"
233
+ input({:name => "cfile", :type => 'file'})
234
+ end
235
+ p do
236
+ input.newfile! :type => "submit", :value => "Upload"
237
+ end
238
+ end
239
+ end
240
+
241
+ def csv_get_id
242
+ form :method => "post" do
243
+ label "ID column: ", :for => "csv_id"
244
+ select(:name => "csv_id") do
245
+ @id_fields.each { |f| option(f) }
246
+ end
247
+ input :type => "submit", :value => "Set ID"
248
+ end
249
+ end
250
+
251
+ def html_diff
252
+ text @table
253
+ hr
254
+ ul do
255
+ li { a "New Diff", :href => R(CSVDifference) }
256
+ li { a "New Key for Diff", :href => R(GenerateDiffReport) }
257
+ li { a "CSV Download", :href => R(CSVDiffReportFormatted,"csv") }
258
+ li { a "Text Download", :href => R(CSVDiffReportFormatted,"txt") }
259
+ li { a "PDF Download", :href => R(CSVDiffReportFormatted,"pdf") }
260
+ end
261
+ end
262
+
263
+ end