ruport 1.6.3 → 1.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/AUTHORS +11 -0
- data/README.rdoc +105 -0
- data/Rakefile +13 -44
- data/examples/add_row_table.rb +46 -0
- data/examples/data/wine.csv +255 -0
- data/examples/pdf_grouping.rb +39 -0
- data/examples/pdf_table.rb +28 -0
- data/examples/pdf_table_from_csv.rb +26 -0
- data/examples/pdf_table_prawn.rb +30 -0
- data/examples/pdf_table_simple.rb +13 -0
- data/lib/ruport.rb +0 -12
- data/lib/ruport/controller.rb +16 -20
- data/lib/ruport/data/feeder.rb +2 -2
- data/lib/ruport/data/grouping.rb +2 -2
- data/lib/ruport/data/table.rb +314 -202
- data/lib/ruport/formatter.rb +53 -52
- data/lib/ruport/formatter/csv.rb +6 -7
- data/lib/ruport/formatter/html.rb +13 -11
- data/lib/ruport/formatter/pdf.rb +73 -75
- data/lib/ruport/formatter/prawn_pdf.rb +72 -0
- data/lib/ruport/formatter/template.rb +1 -1
- data/lib/ruport/version.rb +1 -1
- data/test/controller_test.rb +100 -122
- data/test/csv_formatter_test.rb +15 -15
- data/test/data_feeder_test.rb +26 -26
- data/test/grouping_test.rb +30 -29
- data/test/helpers.rb +18 -10
- data/test/html_formatter_test.rb +24 -24
- data/test/record_test.rb +14 -14
- data/test/samples/sales.csv +21 -0
- data/test/table_pivot_test.rb +68 -24
- data/test/table_test.rb +365 -336
- data/test/template_test.rb +1 -1
- data/test/text_formatter_test.rb +19 -19
- data/util/bench/data/table/bench_init.rb +1 -1
- metadata +123 -75
- data/README +0 -114
- data/test/pdf_formatter_test.rb +0 -354
@@ -0,0 +1,72 @@
|
|
1
|
+
module Ruport
|
2
|
+
class Formatter::PrawnPDF < Formatter
|
3
|
+
|
4
|
+
renders :prawn_pdf, :for =>[Controller::Row, Controller::Table,
|
5
|
+
Controller::Group, Controller::Grouping]
|
6
|
+
|
7
|
+
attr_accessor :pdf
|
8
|
+
|
9
|
+
def method_missing(id,*args, &block)
|
10
|
+
pdf.send(id,*args, &block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
require 'prawn'
|
15
|
+
require 'prawn/layout'
|
16
|
+
end
|
17
|
+
|
18
|
+
def pdf
|
19
|
+
@pdf ||= (options.formatter ||
|
20
|
+
::Prawn::Document.new(options[:pdf_format] || {} ))
|
21
|
+
end
|
22
|
+
|
23
|
+
def draw_table(table, format_opts={})
|
24
|
+
m = "PDF Formatter requires column_names to be defined"
|
25
|
+
raise FormatterError, m if table.column_names.empty?
|
26
|
+
|
27
|
+
table.rename_columns { |c| c.to_s }
|
28
|
+
|
29
|
+
table_array = [table.column_names]
|
30
|
+
table_array += table_to_array(table)
|
31
|
+
table_array.map { |array| array.map! { |elem| elem.class != String ? elem.to_s : elem }}
|
32
|
+
|
33
|
+
if options[:table_format]
|
34
|
+
opt = options[:table_format]
|
35
|
+
else
|
36
|
+
opt = {}
|
37
|
+
end
|
38
|
+
|
39
|
+
pdf.table(table_array,opt)
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
def table_to_array(tbl)
|
44
|
+
tbl.map { |row| row.to_a}
|
45
|
+
end
|
46
|
+
|
47
|
+
def finalize
|
48
|
+
output << pdf.render
|
49
|
+
end
|
50
|
+
|
51
|
+
def build_table_body
|
52
|
+
draw_table(data)
|
53
|
+
end
|
54
|
+
|
55
|
+
def build_group_body
|
56
|
+
render_table data, options.to_hash.merge(:formatter => pdf)
|
57
|
+
end
|
58
|
+
|
59
|
+
def build_grouping_body
|
60
|
+
data.each do |name,group|
|
61
|
+
|
62
|
+
# Group heading
|
63
|
+
move_down(20)
|
64
|
+
text name, :style => :bold, :size => 15
|
65
|
+
|
66
|
+
# Table
|
67
|
+
move_down(10)
|
68
|
+
draw_table group
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -140,7 +140,7 @@ class Ruport::Formatter::TemplateNotDefined < StandardError; end
|
|
140
140
|
#
|
141
141
|
# format_options All options Corresponding values
|
142
142
|
# available to
|
143
|
-
#
|
143
|
+
# ::CSV.new
|
144
144
|
#
|
145
145
|
class Ruport::Formatter::Template < Ruport::Controller::Options
|
146
146
|
|
data/lib/ruport/version.rb
CHANGED
data/test/controller_test.rb
CHANGED
@@ -94,7 +94,7 @@ class SpecialFinalize < Ruport::Formatter
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
-
class TestController < Test
|
97
|
+
class TestController < Minitest::Test
|
98
98
|
|
99
99
|
def teardown
|
100
100
|
Ruport::Formatter::Template.instance_variable_set(:@templates, nil)
|
@@ -115,14 +115,14 @@ class TestController < Test::Unit::TestCase
|
|
115
115
|
context "when using templates" do
|
116
116
|
def specify_apply_template_should_be_called
|
117
117
|
Ruport::Formatter::Template.create(:stub)
|
118
|
-
Table(%w[a b c]).to_csv(:template => :stub) do |r|
|
118
|
+
Ruport.Table(%w[a b c]).to_csv(:template => :stub) do |r|
|
119
119
|
r.formatter.expects(:apply_template)
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
123
123
|
def specify_undefined_template_should_throw_sensible_error
|
124
124
|
assert_raises(Ruport::Formatter::TemplateNotDefined) do
|
125
|
-
Table(%w[a b c]).to_csv(:template => :sub)
|
125
|
+
Ruport.Table(%w[a b c]).to_csv(:template => :sub)
|
126
126
|
end
|
127
127
|
end
|
128
128
|
end
|
@@ -130,7 +130,7 @@ class TestController < Test::Unit::TestCase
|
|
130
130
|
context "when using default templates" do
|
131
131
|
def specify_default_template_should_be_called
|
132
132
|
Ruport::Formatter::Template.create(:default)
|
133
|
-
Table(%w[a b c]).to_csv do |r|
|
133
|
+
Ruport.Table(%w[a b c]).to_csv do |r|
|
134
134
|
r.formatter.expects(:apply_template)
|
135
135
|
assert r.formatter.template == Ruport::Formatter::Template[:default]
|
136
136
|
end
|
@@ -139,7 +139,7 @@ class TestController < Test::Unit::TestCase
|
|
139
139
|
def specify_specific_should_override_default
|
140
140
|
Ruport::Formatter::Template.create(:default)
|
141
141
|
Ruport::Formatter::Template.create(:stub)
|
142
|
-
Table(%w[a b c]).to_csv(:template => :stub) do |r|
|
142
|
+
Ruport.Table(%w[a b c]).to_csv(:template => :stub) do |r|
|
143
143
|
r.formatter.expects(:apply_template)
|
144
144
|
assert r.formatter.template == Ruport::Formatter::Template[:stub]
|
145
145
|
end
|
@@ -147,7 +147,7 @@ class TestController < Test::Unit::TestCase
|
|
147
147
|
|
148
148
|
def specify_should_be_able_to_disable_templates
|
149
149
|
Ruport::Formatter::Template.create(:default)
|
150
|
-
Table(%w[a b c]).to_csv(:template => false) do |r|
|
150
|
+
Ruport.Table(%w[a b c]).to_csv(:template => false) do |r|
|
151
151
|
r.formatter.expects(:apply_template).never
|
152
152
|
end
|
153
153
|
end
|
@@ -176,7 +176,7 @@ class TestController < Test::Unit::TestCase
|
|
176
176
|
def test_using_file_via_rendering_tools
|
177
177
|
f = []
|
178
178
|
File.expects(:open).yields(f)
|
179
|
-
Table(%w[a b c], :data => [[1,2,3],[4,5,6]]).save_as("foo.csv")
|
179
|
+
Ruport.Table(%w[a b c], :data => [[1,2,3],[4,5,6]]).save_as("foo.csv")
|
180
180
|
assert_equal "a,b,c\n1,2,3\n4,5,6\n", f[0]
|
181
181
|
end
|
182
182
|
|
@@ -231,7 +231,7 @@ class TestController < Test::Unit::TestCase
|
|
231
231
|
end
|
232
232
|
|
233
233
|
|
234
|
-
class TestFormatterUsingBuild < Test
|
234
|
+
class TestFormatterUsingBuild < Minitest::Test
|
235
235
|
# This formatter uses the build syntax
|
236
236
|
class UsesBuild < Ruport::Formatter
|
237
237
|
renders :text_using_build, :for => VanillaController
|
@@ -261,7 +261,7 @@ class TestFormatterUsingBuild < Test::Unit::TestCase
|
|
261
261
|
end
|
262
262
|
|
263
263
|
|
264
|
-
class TestFormatterWithLayout < Test
|
264
|
+
class TestFormatterWithLayout < Minitest::Test
|
265
265
|
# This formatter is meant to check out a special case in Ruport's renderer,
|
266
266
|
# in which a layout method is called and yielded to when defined
|
267
267
|
class WithLayout < DummyText
|
@@ -288,7 +288,7 @@ class TestFormatterWithLayout < Test::Unit::TestCase
|
|
288
288
|
end
|
289
289
|
|
290
290
|
|
291
|
-
class TestControllerWithManyHooks < Test
|
291
|
+
class TestControllerWithManyHooks < Minitest::Test
|
292
292
|
# This provides a way to check several hooks that controllers supports
|
293
293
|
class ControllerWithManyHooks < Ruport::Controller
|
294
294
|
add_format DummyText, :text
|
@@ -351,13 +351,13 @@ class TestControllerWithManyHooks < Test::Unit::TestCase
|
|
351
351
|
end
|
352
352
|
|
353
353
|
def test_finalize_again
|
354
|
-
|
354
|
+
assert_raises(Ruport::Controller::StageAlreadyDefinedError) {
|
355
355
|
ControllerWithManyHooks.finalize :report
|
356
356
|
}
|
357
357
|
end
|
358
358
|
|
359
359
|
def test_prepare_again
|
360
|
-
|
360
|
+
assert_raises(Ruport::Controller::StageAlreadyDefinedError) {
|
361
361
|
ControllerWithManyHooks.prepare :foo
|
362
362
|
}
|
363
363
|
end
|
@@ -385,13 +385,13 @@ class TestControllerWithManyHooks < Test::Unit::TestCase
|
|
385
385
|
a = ControllerWithManyHooks.dup
|
386
386
|
a.required_option :title
|
387
387
|
|
388
|
-
|
388
|
+
assert_raises(Ruport::Controller::RequiredOptionNotSet) { a.render(:text) }
|
389
389
|
end
|
390
390
|
|
391
391
|
end
|
392
392
|
|
393
393
|
|
394
|
-
class TestControllerWithRunHook < Test
|
394
|
+
class TestControllerWithRunHook < Minitest::Test
|
395
395
|
|
396
396
|
class ControllerWithRunHook < Ruport::Controller
|
397
397
|
add_format DummyText, :text
|
@@ -416,7 +416,7 @@ class TestControllerWithRunHook < Test::Unit::TestCase
|
|
416
416
|
end
|
417
417
|
|
418
418
|
|
419
|
-
class TestControllerWithHelperModule < Test
|
419
|
+
class TestControllerWithHelperModule < Minitest::Test
|
420
420
|
|
421
421
|
class ControllerWithHelperModule < VanillaController
|
422
422
|
|
@@ -437,7 +437,7 @@ class TestControllerWithHelperModule < Test::Unit::TestCase
|
|
437
437
|
end
|
438
438
|
|
439
439
|
|
440
|
-
class TestMultiPurposeFormatter < Test
|
440
|
+
class TestMultiPurposeFormatter < Minitest::Test
|
441
441
|
# This provides a way to check the multi-format hooks for the Controller
|
442
442
|
class MultiPurposeFormatter < Ruport::Formatter
|
443
443
|
|
@@ -489,40 +489,40 @@ class TestMultiPurposeFormatter < Test::Unit::TestCase
|
|
489
489
|
end
|
490
490
|
|
491
491
|
|
492
|
-
class TestFormatterErbHelper < Test
|
492
|
+
class TestFormatterErbHelper < Minitest::Test
|
493
493
|
class ErbFormatter < Ruport::Formatter
|
494
|
-
|
494
|
+
|
495
495
|
renders :terb, :for => VanillaController
|
496
|
-
|
497
|
-
def build_body
|
496
|
+
|
497
|
+
def build_body
|
498
498
|
# demonstrate local binding
|
499
|
-
@foo = "bar"
|
499
|
+
@foo = "bar"
|
500
500
|
if options.binding
|
501
|
-
output << erb("Binding Override: <%= reverse %>",
|
502
|
-
:binding => options.binding)
|
503
|
-
else
|
504
|
-
output << erb("Default Binding: <%= @foo %>")
|
505
|
-
end
|
501
|
+
output << erb("Binding Override: <%= reverse.inspect %>",
|
502
|
+
:binding => options.binding)
|
503
|
+
else
|
504
|
+
output << erb("Default Binding: <%= @foo %>")
|
505
|
+
end
|
506
506
|
end
|
507
507
|
|
508
508
|
end
|
509
509
|
|
510
|
-
|
510
|
+
#FIXME: need to test file
|
511
511
|
|
512
512
|
def test_self_bound
|
513
513
|
assert_equal "Default Binding: bar", VanillaController.render_terb
|
514
514
|
end
|
515
|
-
|
515
|
+
|
516
516
|
def test_custom_bound
|
517
517
|
a = [1,2,3]
|
518
518
|
arr_binding = a.instance_eval { binding }
|
519
|
-
assert_equal "Binding Override:
|
519
|
+
assert_equal "Binding Override: [3, 2, 1]",
|
520
520
|
VanillaController.render_terb(:binding => arr_binding)
|
521
521
|
end
|
522
|
-
end
|
522
|
+
end
|
523
523
|
|
524
524
|
|
525
|
-
class TestOptionReaders < Test
|
525
|
+
class TestOptionReaders < Minitest::Test
|
526
526
|
|
527
527
|
class ControllerForCheckingOptionReaders < Ruport::Controller
|
528
528
|
required_option :foo
|
@@ -557,7 +557,7 @@ class TestOptionReaders < Test::Unit::TestCase
|
|
557
557
|
|
558
558
|
end
|
559
559
|
|
560
|
-
class TestSetupOrdering < Test
|
560
|
+
class TestSetupOrdering < Minitest::Test
|
561
561
|
|
562
562
|
class ControllerWithSetup < Ruport::Controller
|
563
563
|
stage :bar
|
@@ -630,24 +630,20 @@ class ControllerWithAnonymousFormatters < Ruport::Controller
|
|
630
630
|
|
631
631
|
end
|
632
632
|
|
633
|
-
class TestAnonymousFormatter < Test
|
634
|
-
context "When using built in Ruport formatters" do
|
633
|
+
class TestAnonymousFormatter < Minitest::Test
|
635
634
|
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
635
|
+
def test_text_formatter_shortcut_is_accessible
|
636
|
+
assert_equal "Hello world", ControllerWithAnonymousFormatters.render_text
|
637
|
+
assert_equal "1,2,3\n", ControllerWithAnonymousFormatters.render_csv
|
638
|
+
assert_equal "<h1>Hi there</h1>", ControllerWithAnonymousFormatters.render_html
|
639
|
+
if RUBY_VERSION < "1.9"
|
640
640
|
assert_not_nil ControllerWithAnonymousFormatters.render_pdf
|
641
641
|
end
|
642
|
-
|
643
642
|
end
|
644
643
|
|
645
|
-
|
646
|
-
|
647
|
-
assert_equal "This is Custom!", ControllerWithAnonymousFormatters.render_custom
|
648
|
-
end
|
644
|
+
def test_custom_formatter_shortcut_is_accessible
|
645
|
+
assert_equal "This is Custom!", ControllerWithAnonymousFormatters.render_custom
|
649
646
|
end
|
650
|
-
|
651
647
|
end
|
652
648
|
|
653
649
|
# Used to ensure that problems in controller code aren't mistakenly intercepted
|
@@ -663,106 +659,88 @@ class MisbehavingFormatter < Ruport::Formatter
|
|
663
659
|
end
|
664
660
|
end
|
665
661
|
|
666
|
-
class TestMisbehavingController < Test
|
662
|
+
class TestMisbehavingController < Minitest::Test
|
667
663
|
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
MisbehavingController.render :text
|
672
|
-
end
|
664
|
+
def test_controller_errors_should_bubble_up
|
665
|
+
assert_raises(NoMethodError) do
|
666
|
+
MisbehavingController.render :text
|
673
667
|
end
|
674
668
|
end
|
675
669
|
|
676
670
|
end
|
677
671
|
|
678
|
-
class TestControllerHooks < Test
|
679
|
-
|
680
|
-
context "when renderable_data omitted" do
|
681
|
-
|
682
|
-
require "mocha"
|
683
|
-
|
684
|
-
class DummyObject
|
685
|
-
include Ruport::Controller::Hooks
|
686
|
-
renders_as_table
|
687
|
-
end
|
672
|
+
class TestControllerHooks < Minitest::Test
|
688
673
|
|
689
|
-
|
690
|
-
a = DummyObject.new
|
691
|
-
rend = mock("renderer")
|
692
|
-
rend.expects(:data=).with(a)
|
693
|
-
Ruport::Controller::Table.expects(:render).with(:csv,{}).yields(rend)
|
694
|
-
a.as(:csv)
|
695
|
-
end
|
674
|
+
require "mocha"
|
696
675
|
|
676
|
+
class DummyObject
|
677
|
+
include Ruport::Controller::Hooks
|
678
|
+
renders_as_table
|
697
679
|
end
|
698
680
|
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
1
|
707
|
-
end
|
708
|
-
end
|
709
|
-
|
710
|
-
def specify_should_return_results_of_renderable_data
|
711
|
-
a = DummyObject2.new
|
712
|
-
rend = mock("renderer")
|
713
|
-
rend.expects(:data=).with(1)
|
714
|
-
Ruport::Controller::Table.expects(:render).with(:csv,{}).yields(rend)
|
715
|
-
a.as(:csv)
|
716
|
-
end
|
681
|
+
def test_should_return_self
|
682
|
+
a = DummyObject.new
|
683
|
+
rend = mock("renderer")
|
684
|
+
rend.expects(:data=).with(a)
|
685
|
+
Ruport::Controller::Table.expects(:render).with(:csv,{}).yields(rend)
|
686
|
+
a.as(:csv)
|
687
|
+
end
|
717
688
|
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
def renderable_data
|
723
|
-
raise ArgumentError
|
724
|
-
end
|
725
|
-
end
|
689
|
+
class DummyObject2
|
690
|
+
include Ruport::Controller::Hooks
|
691
|
+
renders_as_table
|
726
692
|
|
727
|
-
def
|
728
|
-
|
693
|
+
def renderable_data(format)
|
694
|
+
1
|
729
695
|
end
|
696
|
+
end
|
730
697
|
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
1
|
739
|
-
when :csv
|
740
|
-
2
|
741
|
-
end
|
742
|
-
end
|
743
|
-
end
|
698
|
+
def test_should_return_results_of_renderable_data
|
699
|
+
a = DummyObject2.new
|
700
|
+
rend = mock("renderer")
|
701
|
+
rend.expects(:data=).with(1)
|
702
|
+
Ruport::Controller::Table.expects(:render).with(:csv,{}).yields(rend)
|
703
|
+
a.as(:csv)
|
704
|
+
end
|
744
705
|
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
706
|
+
class DummyObject3
|
707
|
+
include Ruport::Controller::Hooks
|
708
|
+
renders_as_table
|
709
|
+
|
710
|
+
def renderable_data
|
711
|
+
raise ArgumentError
|
751
712
|
end
|
713
|
+
end
|
752
714
|
|
753
|
-
|
754
|
-
|
755
|
-
|
715
|
+
def test_should_not_mask_errors
|
716
|
+
assert_raises(ArgumentError) { DummyObject3.new.as(:csv) }
|
717
|
+
end
|
756
718
|
|
757
|
-
|
719
|
+
class DummyObject4
|
720
|
+
include Ruport::Controller::Hooks
|
721
|
+
renders_as_table
|
758
722
|
|
759
|
-
|
760
|
-
|
723
|
+
def renderable_data(format)
|
724
|
+
case format
|
725
|
+
when :html
|
726
|
+
1
|
727
|
+
when :csv
|
728
|
+
2
|
761
729
|
end
|
762
|
-
|
763
730
|
end
|
764
731
|
end
|
765
732
|
|
733
|
+
def test_should_return_results_of_renderable_data_using_format
|
734
|
+
a = DummyObject4.new
|
735
|
+
rend = mock("renderer")
|
736
|
+
rend.expects(:data=).with(2)
|
737
|
+
Ruport::Controller::Table.expects(:render).with(:csv,{}).yields(rend)
|
738
|
+
a.as(:csv)
|
739
|
+
end
|
766
740
|
|
767
|
-
|
741
|
+
def test_an_unknown_format_error_should_be_raised
|
742
|
+
assert_raises(Ruport::Controller::UnknownFormatError) do
|
743
|
+
Ruport::Controller.render_foo
|
744
|
+
end
|
745
|
+
end
|
768
746
|
end
|