ruport 1.4.0 → 1.6.0
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.
- data/Rakefile +3 -3
- data/examples/anon.rb +43 -0
- data/examples/btree/commaleon/commaleon.rb +9 -9
- data/examples/centered_pdf_text_box.rb +7 -7
- data/examples/line_plotter.rb +1 -1
- data/examples/pdf_report_with_common_base.rb +4 -4
- data/examples/png_embed.rb +4 -4
- data/examples/row_renderer.rb +4 -4
- data/examples/simple_pdf_lines.rb +1 -1
- data/examples/trac_ticket_status.rb +1 -1
- data/lib/ruport.rb +15 -3
- data/lib/ruport/{renderer.rb → controller.rb} +183 -87
- data/lib/ruport/{renderer → controller}/grouping.rb +5 -5
- data/lib/ruport/{renderer → controller}/table.rb +5 -5
- data/lib/ruport/data/grouping.rb +2 -2
- data/lib/ruport/data/record.rb +4 -2
- data/lib/ruport/data/table.rb +128 -4
- data/lib/ruport/formatter.rb +36 -37
- data/lib/ruport/formatter/csv.rb +37 -20
- data/lib/ruport/formatter/html.rb +11 -12
- data/lib/ruport/formatter/pdf.rb +10 -6
- data/lib/ruport/formatter/template.rb +1 -1
- data/lib/ruport/formatter/text.rb +8 -15
- data/test/{renderer_test.rb → controller_test.rb} +179 -74
- data/test/csv_formatter_test.rb +6 -6
- data/test/grouping_test.rb +4 -4
- data/test/helpers.rb +1 -0
- data/test/html_formatter_test.rb +18 -18
- data/test/pdf_formatter_test.rb +28 -3
- data/test/record_test.rb +2 -2
- data/test/table_pivot_test.rb +134 -0
- data/test/table_test.rb +10 -3
- data/test/text_formatter_test.rb +6 -6
- data/util/bench/data/record/bench_as_vs_to.rb +1 -1
- metadata +19 -16
@@ -1,6 +1,6 @@
|
|
1
1
|
# Ruport : Extensible Reporting System
|
2
2
|
#
|
3
|
-
#
|
3
|
+
# controller/grouping.rb : Group data controller for Ruby Reports
|
4
4
|
#
|
5
5
|
# Written by Michael Milner, 2007.
|
6
6
|
# Copyright (C) 2007, All Rights Reserved
|
@@ -10,7 +10,7 @@
|
|
10
10
|
#
|
11
11
|
module Ruport
|
12
12
|
|
13
|
-
# This class implements the basic
|
13
|
+
# This class implements the basic controller for a single group of data.
|
14
14
|
#
|
15
15
|
# == Supported Formatters
|
16
16
|
#
|
@@ -29,13 +29,13 @@ module Ruport
|
|
29
29
|
# * build_group_body
|
30
30
|
# * build_group_footer
|
31
31
|
#
|
32
|
-
class
|
32
|
+
class Controller::Group < Controller
|
33
33
|
options { |o| o.show_table_headers = true }
|
34
34
|
|
35
35
|
stage :group_header, :group_body, :group_footer
|
36
36
|
end
|
37
37
|
|
38
|
-
# This class implements the basic
|
38
|
+
# This class implements the basic controller for data groupings in Ruport
|
39
39
|
# (a collection of Groups).
|
40
40
|
#
|
41
41
|
# == Supported Formatters
|
@@ -57,7 +57,7 @@ module Ruport
|
|
57
57
|
# * build_grouping_footer
|
58
58
|
# * finalize_grouping
|
59
59
|
#
|
60
|
-
class
|
60
|
+
class Controller::Grouping < Controller
|
61
61
|
options do |o|
|
62
62
|
o.show_group_headers = true
|
63
63
|
o.style = :inline
|
@@ -1,11 +1,11 @@
|
|
1
|
-
#
|
1
|
+
# controller/table.rb : Tabular data controller for Ruby Reports
|
2
2
|
#
|
3
3
|
# Written by Gregory Brown, December 2006. Copyright 2006, All Rights Reserved
|
4
4
|
# This is Free Software, please see LICENSE and COPYING for details.
|
5
5
|
|
6
6
|
module Ruport
|
7
7
|
|
8
|
-
# This class implements the basic
|
8
|
+
# This class implements the basic controller for table rows.
|
9
9
|
#
|
10
10
|
# == Supported Formatters
|
11
11
|
#
|
@@ -17,11 +17,11 @@ module Ruport
|
|
17
17
|
#
|
18
18
|
# * build_row
|
19
19
|
#
|
20
|
-
class
|
20
|
+
class Controller::Row < Controller
|
21
21
|
stage :row
|
22
22
|
end
|
23
23
|
|
24
|
-
# This class implements the basic tabular data
|
24
|
+
# This class implements the basic tabular data controller for Ruport.
|
25
25
|
#
|
26
26
|
# == Supported Formatters
|
27
27
|
#
|
@@ -42,7 +42,7 @@ module Ruport
|
|
42
42
|
# * build_table_footer
|
43
43
|
# * finalize_table
|
44
44
|
#
|
45
|
-
class
|
45
|
+
class Controller::Table < Controller
|
46
46
|
options { |o| o.show_table_headers = true }
|
47
47
|
|
48
48
|
prepare :table
|
data/lib/ruport/data/grouping.rb
CHANGED
@@ -44,7 +44,7 @@ module Ruport::Data
|
|
44
44
|
super
|
45
45
|
end
|
46
46
|
|
47
|
-
include Ruport::
|
47
|
+
include Ruport::Controller::Hooks
|
48
48
|
renders_as_group
|
49
49
|
|
50
50
|
def self.inherited(base) #:nodoc:
|
@@ -340,7 +340,7 @@ module Ruport::Data
|
|
340
340
|
|
341
341
|
alias_method :sum, :sigma
|
342
342
|
|
343
|
-
include Ruport::
|
343
|
+
include Ruport::Controller::Hooks
|
344
344
|
renders_as_grouping
|
345
345
|
|
346
346
|
def self.inherited(base) #:nodoc:
|
data/lib/ruport/data/record.rb
CHANGED
@@ -18,7 +18,9 @@ module Ruport::Data
|
|
18
18
|
#
|
19
19
|
class Record
|
20
20
|
|
21
|
-
|
21
|
+
if RUBY_VERSION < "1.9"
|
22
|
+
private :id
|
23
|
+
end
|
22
24
|
|
23
25
|
include Enumerable
|
24
26
|
|
@@ -231,7 +233,7 @@ module Ruport::Data
|
|
231
233
|
# Internals / Helpers #
|
232
234
|
#######################
|
233
235
|
|
234
|
-
include Ruport::
|
236
|
+
include Ruport::Controller::Hooks
|
235
237
|
renders_as_row
|
236
238
|
|
237
239
|
def self.inherited(base) #:nodoc:
|
data/lib/ruport/data/table.rb
CHANGED
@@ -24,6 +24,130 @@ module Ruport::Data
|
|
24
24
|
#
|
25
25
|
class Table
|
26
26
|
|
27
|
+
class Pivot #:nodoc:
|
28
|
+
|
29
|
+
def initialize(table, group_col, pivot_col, summary_col, options = {})
|
30
|
+
@table = table
|
31
|
+
@group_column = group_col
|
32
|
+
@pivot_column = pivot_col
|
33
|
+
@summary_column = summary_col
|
34
|
+
@pivot_order = options[:pivot_order]
|
35
|
+
end
|
36
|
+
|
37
|
+
def convert_row_order_to_group_order(row_order_spec)
|
38
|
+
case row_order_spec
|
39
|
+
when Array
|
40
|
+
proc {|group|
|
41
|
+
row_order_spec.map {|e| group[0][e].to_s }
|
42
|
+
}
|
43
|
+
when Proc
|
44
|
+
proc {|group|
|
45
|
+
if row_order_spec.arity == 2
|
46
|
+
row_order_spec.call(group[0], group.name)
|
47
|
+
else
|
48
|
+
row_order_spec.call(group[0])
|
49
|
+
end
|
50
|
+
}
|
51
|
+
when NilClass
|
52
|
+
nil
|
53
|
+
else
|
54
|
+
proc {|group| group[0][row_order_spec].to_s }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def columns_from_pivot
|
59
|
+
ordering = convert_row_order_to_group_order(@pivot_order)
|
60
|
+
pivot_column_grouping = Grouping(@table, :by => @pivot_column)
|
61
|
+
pivot_column_grouping.each {|n,g| g.add_column(n) { n }}
|
62
|
+
pivot_column_grouping.sort_grouping_by!(ordering) if ordering
|
63
|
+
result = []
|
64
|
+
pivot_column_grouping.each {|name,_| result << name }
|
65
|
+
result
|
66
|
+
end
|
67
|
+
|
68
|
+
def group_column_entries
|
69
|
+
@table.map {|row| row[@group_column]}.uniq
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_table
|
73
|
+
result = Table()
|
74
|
+
result.add_column(@group_column)
|
75
|
+
pivoted_columns = columns_from_pivot
|
76
|
+
pivoted_columns.each { |name| result.add_column(name) }
|
77
|
+
outer_grouping = Grouping(@table, :by => @group_column)
|
78
|
+
group_column_entries.each {|outer_group_name|
|
79
|
+
outer_group = outer_grouping[outer_group_name]
|
80
|
+
pivot_values = pivoted_columns.inject({}) do |hsh, e|
|
81
|
+
matching_rows = outer_group.rows_with(@pivot_column => e)
|
82
|
+
hsh[e] = matching_rows.first && matching_rows.first[@summary_column]
|
83
|
+
hsh
|
84
|
+
end
|
85
|
+
result << [outer_group_name] + pivoted_columns.map {|e|
|
86
|
+
pivot_values[e]
|
87
|
+
}
|
88
|
+
}
|
89
|
+
result
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
# Creates a new table with values from the specified pivot column
|
95
|
+
# transformed into columns.
|
96
|
+
#
|
97
|
+
# Required options:
|
98
|
+
# <b><tt>:group_by</tt></b>:: The name of a column whose unique
|
99
|
+
# values should become rows in the new
|
100
|
+
# table.
|
101
|
+
#
|
102
|
+
# <b><tt>:values</tt></b>:: The name of a column that should supply
|
103
|
+
# the values for the pivoted columns.
|
104
|
+
#
|
105
|
+
# Optional:
|
106
|
+
# <b><tt>:pivot_order</tt></b>:: An ordering specification for the
|
107
|
+
# pivoted columns, in terms of the source
|
108
|
+
# rows. If this is a Proc there is an
|
109
|
+
# optional second argument that receives
|
110
|
+
# the name of the pivot column, which due
|
111
|
+
# to implementation oddity currently is
|
112
|
+
# removed from the row provided in the
|
113
|
+
# first argument. This wart will likely
|
114
|
+
# be fixed in a future version.
|
115
|
+
#
|
116
|
+
# Example:
|
117
|
+
#
|
118
|
+
# Given a table <em>my_table</em>:
|
119
|
+
# +-------------------------+
|
120
|
+
# | Group | Segment | Value |
|
121
|
+
# +-------------------------+
|
122
|
+
# | A | 1 | 0 |
|
123
|
+
# | A | 2 | 1 |
|
124
|
+
# | B | 1 | 2 |
|
125
|
+
# | B | 2 | 3 |
|
126
|
+
# +-------------------------+
|
127
|
+
#
|
128
|
+
# Pivoting the table on the Segment column:
|
129
|
+
#
|
130
|
+
# my_table.pivot('Segment', :group_by => 'Group', :values => 'Value',
|
131
|
+
# :pivot_order => proc {|row, name| name})
|
132
|
+
#
|
133
|
+
# Yields a new table like this:
|
134
|
+
# +---------------+
|
135
|
+
# | Group | 1 | 2 |
|
136
|
+
# +---------------+
|
137
|
+
# | A | 0 | 1 |
|
138
|
+
# | B | 2 | 3 |
|
139
|
+
# +---------------+
|
140
|
+
#
|
141
|
+
def pivot(pivot_column, options = {})
|
142
|
+
group_column = options[:group_by] ||
|
143
|
+
raise(ArgumentError, ":group_by option required")
|
144
|
+
value_column = options[:values] ||
|
145
|
+
raise(ArgumentError, ":values option required")
|
146
|
+
Pivot.new(
|
147
|
+
self, group_column, pivot_column, value_column, options
|
148
|
+
).to_table
|
149
|
+
end
|
150
|
+
|
27
151
|
# === Overview
|
28
152
|
#
|
29
153
|
# This module provides facilities for creating tables from csv data.
|
@@ -62,8 +186,7 @@ module Ruport::Data
|
|
62
186
|
|
63
187
|
options = {:has_names => true,
|
64
188
|
:csv_options => {} }.merge(options)
|
65
|
-
|
66
|
-
# if people want to use FCSV's header support, let them
|
189
|
+
|
67
190
|
adjust_options_for_fcsv_headers(options)
|
68
191
|
|
69
192
|
table = self.new(options) do |feeder|
|
@@ -111,7 +234,7 @@ module Ruport::Data
|
|
111
234
|
include Enumerable
|
112
235
|
extend FromCSV
|
113
236
|
|
114
|
-
include Ruport::
|
237
|
+
include Ruport::Controller::Hooks
|
115
238
|
renders_as_table
|
116
239
|
|
117
240
|
def self.inherited(base) #:nodoc:
|
@@ -403,7 +526,8 @@ module Ruport::Data
|
|
403
526
|
# table.column_names.include?("a") #=> false
|
404
527
|
#
|
405
528
|
def rename_column(old_name,new_name)
|
406
|
-
|
529
|
+
index = column_names.index(old_name) or return
|
530
|
+
self.column_names[index] = new_name
|
407
531
|
each { |r| r.rename_attribute(old_name,new_name,false)}
|
408
532
|
end
|
409
533
|
|
data/lib/ruport/formatter.rb
CHANGED
@@ -11,7 +11,7 @@ module Ruport
|
|
11
11
|
# Formatter is the base class for Ruport's format implementations.
|
12
12
|
#
|
13
13
|
# Typically, a Formatter will implement one or more output types,
|
14
|
-
# and be registered with one or more
|
14
|
+
# and be registered with one or more Controller classes.
|
15
15
|
#
|
16
16
|
# This class provides all the necessary base functionality to make
|
17
17
|
# use of Ruport's rendering system, including option handling, data
|
@@ -20,35 +20,35 @@ module Ruport
|
|
20
20
|
# The following example should provide a general idea of how formatters
|
21
21
|
# work, but see the built in formatters for reference implementations.
|
22
22
|
#
|
23
|
-
# A simple
|
23
|
+
# A simple Controller definition is included to help show the example in
|
24
24
|
# context, but you can also build your own custom interface to formatter
|
25
25
|
# if you wish.
|
26
26
|
#
|
27
|
-
# class
|
27
|
+
# class ReverseController < Ruport::Controller
|
28
28
|
# stage :reversed_header, :reversed_body
|
29
29
|
# end
|
30
30
|
#
|
31
31
|
# class ReversedText < Ruport::Formatter
|
32
32
|
#
|
33
|
-
# # Hooks formatter up to
|
34
|
-
# renders :txt, :for =>
|
33
|
+
# # Hooks formatter up to controller
|
34
|
+
# renders :txt, :for => ReverseController
|
35
35
|
#
|
36
|
-
# # Implements
|
37
|
-
# # but can be used by any
|
36
|
+
# # Implements ReverseController's :reversed_header hook
|
37
|
+
# # but can be used by any controller
|
38
38
|
# def build_reversed_header
|
39
39
|
# output << "#{options.header_text}\n"
|
40
40
|
# output << "The reversed text will follow\n"
|
41
41
|
# end
|
42
42
|
#
|
43
|
-
# # Implements
|
44
|
-
# # but can be used by any
|
43
|
+
# # Implements ReverseController's :reversed_body hook
|
44
|
+
# # but can be used by any controller
|
45
45
|
# def build_reversed_body
|
46
46
|
# output << data.reverse << "\n"
|
47
47
|
# end
|
48
48
|
#
|
49
49
|
# end
|
50
50
|
#
|
51
|
-
# puts
|
51
|
+
# puts ReverseController.render_txt(:data => "apple",
|
52
52
|
# :header_text => "Hello Mike, Hello Joe!")
|
53
53
|
#
|
54
54
|
# -----
|
@@ -64,48 +64,40 @@ module Ruport
|
|
64
64
|
# capabilities within your custom formatters
|
65
65
|
#
|
66
66
|
module RenderingTools
|
67
|
-
#
|
68
|
-
# each row to render_row with the given options.
|
69
|
-
def render_data_by_row(options={},&block)
|
70
|
-
data.each do |r|
|
71
|
-
render_row(r,options,&block)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
# Uses Renderer::Row to render the Row object with the
|
67
|
+
# Uses Controller::Row to render the Row object with the
|
76
68
|
# given options.
|
77
69
|
#
|
78
70
|
# Sets the <tt>:io</tt> attribute by default to the existing
|
79
71
|
# formatter's <tt>output</tt> object.
|
80
72
|
def render_row(row,options={},&block)
|
81
|
-
render_helper(
|
73
|
+
render_helper(Controller::Row,row,options,&block)
|
82
74
|
end
|
83
75
|
|
84
|
-
# Uses
|
76
|
+
# Uses Controller::Table to render the Table object with the
|
85
77
|
# given options.
|
86
78
|
#
|
87
79
|
# Sets the :io attribute by default to the existing formatter's
|
88
80
|
# output object.
|
89
81
|
def render_table(table,options={},&block)
|
90
|
-
render_helper(
|
82
|
+
render_helper(Controller::Table,table,options,&block)
|
91
83
|
end
|
92
84
|
|
93
|
-
# Uses
|
85
|
+
# Uses Controller::Group to render the Group object with the
|
94
86
|
# given options.
|
95
87
|
#
|
96
88
|
# Sets the :io attribute by default to the existing formatter's
|
97
89
|
# output object.
|
98
90
|
def render_group(group,options={},&block)
|
99
|
-
render_helper(
|
91
|
+
render_helper(Controller::Group,group,options,&block)
|
100
92
|
end
|
101
93
|
|
102
|
-
# Uses
|
94
|
+
# Uses Controller::Grouping to render the Grouping object with the
|
103
95
|
# given options.
|
104
96
|
#
|
105
97
|
# Sets the :io attribute by default to the existing formatter's
|
106
98
|
# output object.
|
107
99
|
def render_grouping(grouping,options={},&block)
|
108
|
-
render_helper(
|
100
|
+
render_helper(Controller::Grouping,grouping,options,&block)
|
109
101
|
end
|
110
102
|
|
111
103
|
# Iterates through the data in the grouping and renders each group
|
@@ -135,21 +127,21 @@ module Ruport
|
|
135
127
|
|
136
128
|
include RenderingTools
|
137
129
|
|
138
|
-
# Set by the <tt>:data</tt> attribute from
|
139
|
-
|
130
|
+
# Set by the <tt>:data</tt> attribute from Controller#render
|
131
|
+
attr_reader :data
|
140
132
|
|
141
|
-
# Set automatically by
|
133
|
+
# Set automatically by Controller#render(format) or Controller#render_format
|
142
134
|
attr_accessor :format
|
143
135
|
|
144
|
-
# Set automatically by
|
136
|
+
# Set automatically by Controller#render as a Controller::Options object built
|
145
137
|
# by the hash provided.
|
146
138
|
attr_writer :options
|
147
139
|
|
148
|
-
# Registers the formatter with one or more
|
140
|
+
# Registers the formatter with one or more Controllers.
|
149
141
|
#
|
150
|
-
# renders :pdf, :for =>
|
151
|
-
# render :text, :for => [
|
152
|
-
# renders [:csv,:html], :for =>
|
142
|
+
# renders :pdf, :for => MyController
|
143
|
+
# render :text, :for => [MyController,YourController]
|
144
|
+
# renders [:csv,:html], :for => YourController
|
153
145
|
#
|
154
146
|
def self.renders(fmts,options={})
|
155
147
|
Array(fmts).each do |format|
|
@@ -164,7 +156,7 @@ module Ruport
|
|
164
156
|
# following syntax:
|
165
157
|
#
|
166
158
|
# class ReversedText < Ruport::Formatter
|
167
|
-
# renders :txt, :for =>
|
159
|
+
# renders :txt, :for => ReverseController
|
168
160
|
#
|
169
161
|
# build :reversed_header do
|
170
162
|
# output << "#{options.header_text}\n"
|
@@ -196,11 +188,18 @@ module Ruport
|
|
196
188
|
@output ||= ""
|
197
189
|
end
|
198
190
|
|
199
|
-
# Provides a
|
191
|
+
# Provides a Controller::Options object for storing formatting options.
|
200
192
|
def options
|
201
|
-
@options ||=
|
193
|
+
@options ||= Controller::Options.new
|
202
194
|
end
|
203
195
|
|
196
|
+
# Sets the data object, making a local copy using #dup. This may have
|
197
|
+
# a significant overhead for large tables, so formatters which don't
|
198
|
+
# modify the data object may wish to override this.
|
199
|
+
def data=(val)
|
200
|
+
@data = val.dup
|
201
|
+
end
|
202
|
+
|
204
203
|
# Clears the output.
|
205
204
|
def clear_output
|
206
205
|
@output.replace("")
|
data/lib/ruport/formatter/csv.rb
CHANGED
@@ -14,7 +14,7 @@
|
|
14
14
|
module Ruport
|
15
15
|
|
16
16
|
# This formatter implements the CSV format for Ruport's Row, Table, Group
|
17
|
-
# and Grouping
|
17
|
+
# and Grouping controllers. It is a light wrapper around
|
18
18
|
# James Edward Gray II's FasterCSV.
|
19
19
|
#
|
20
20
|
# === Rendering Options
|
@@ -23,14 +23,22 @@ module Ruport
|
|
23
23
|
#
|
24
24
|
# <tt>:format_options</tt> A hash of FasterCSV options
|
25
25
|
#
|
26
|
+
# <tt>:formatter</tt> An existing FasterCSV object to write to
|
27
|
+
#
|
26
28
|
# <tt>:show_table_headers</tt> True by default
|
27
29
|
#
|
28
30
|
# <tt>:show_group_headers</tt> True by default
|
29
31
|
#
|
30
32
|
class Formatter::CSV < Formatter
|
31
33
|
|
32
|
-
renders :csv, :for => [
|
33
|
-
|
34
|
+
renders :csv, :for => [ Controller::Row, Controller::Table,
|
35
|
+
Controller::Group, Controller::Grouping ]
|
36
|
+
|
37
|
+
def initialize
|
38
|
+
require "fastercsv" unless RUBY_VERSION > "1.9"
|
39
|
+
end
|
40
|
+
|
41
|
+
attr_writer :csv_writer
|
34
42
|
|
35
43
|
# Hook for setting available options using a template. See the template
|
36
44
|
# documentation for the available options and their format.
|
@@ -41,37 +49,46 @@ module Ruport
|
|
41
49
|
options.format_options ||= template.format_options
|
42
50
|
end
|
43
51
|
|
52
|
+
# Returns the current FCSV object or creates a new one if it has not
|
53
|
+
# been set yet. Note that FCSV(sig) has a cache and returns the *same*
|
54
|
+
# FCSV object if writing to the same underlying output with the same
|
55
|
+
# options.
|
56
|
+
#
|
57
|
+
def csv_writer
|
58
|
+
@csv_writer ||= options.formatter ||
|
59
|
+
FCSV(output, options.format_options || {})
|
60
|
+
end
|
61
|
+
|
44
62
|
# Generates table header by turning column_names into a CSV row.
|
45
|
-
# Uses the row
|
63
|
+
# Uses the row controller to generate the actual formatted output
|
46
64
|
#
|
47
65
|
# This method does not do anything if options.show_table_headers is false
|
48
66
|
# or the Data::Table has no column names.
|
49
67
|
def build_table_header
|
50
68
|
unless data.column_names.empty? || !options.show_table_headers
|
51
|
-
render_row data.column_names, :format_options => options.format_options
|
69
|
+
render_row data.column_names, :format_options => options.format_options,
|
70
|
+
:formatter => csv_writer
|
52
71
|
end
|
53
72
|
end
|
54
73
|
|
55
|
-
# Calls the row
|
74
|
+
# Calls the row controller for each row in the Data::Table
|
56
75
|
def build_table_body
|
57
|
-
|
58
|
-
|
59
|
-
}
|
76
|
+
fcsv = csv_writer
|
77
|
+
data.each { |row| fcsv << row }
|
60
78
|
end
|
61
79
|
|
62
80
|
# Produces CSV output for a data row.
|
63
|
-
def build_row
|
64
|
-
|
65
|
-
output << FCSV.generate_line(data,options.format_options || {})
|
81
|
+
def build_row(data = self.data)
|
82
|
+
csv_writer << data
|
66
83
|
end
|
67
84
|
|
68
85
|
# Renders the header for a group using the group name.
|
69
86
|
#
|
70
87
|
def build_group_header
|
71
|
-
|
88
|
+
csv_writer << [data.name.to_s] << []
|
72
89
|
end
|
73
90
|
|
74
|
-
# Renders the group body - uses the table
|
91
|
+
# Renders the group body - uses the table controller to generate the output.
|
75
92
|
#
|
76
93
|
def build_group_body
|
77
94
|
render_table data, options.to_hash
|
@@ -82,7 +99,7 @@ module Ruport
|
|
82
99
|
#
|
83
100
|
def build_grouping_header
|
84
101
|
unless options.style == :inline
|
85
|
-
|
102
|
+
csv_writer << [data.grouped_by] + grouping_columns
|
86
103
|
end
|
87
104
|
end
|
88
105
|
|
@@ -101,17 +118,17 @@ module Ruport
|
|
101
118
|
private
|
102
119
|
|
103
120
|
def grouping_columns
|
104
|
-
|
105
|
-
data.data.to_a[0][1].column_names.to_csv
|
121
|
+
data.data.to_a[0][1].column_names
|
106
122
|
end
|
107
123
|
|
108
124
|
def render_justified_or_raw_grouping
|
109
125
|
data.each do |_,group|
|
110
|
-
|
126
|
+
prefix = [group.name.to_s]
|
111
127
|
group.each do |row|
|
112
|
-
|
128
|
+
csv_writer << prefix + row.to_a
|
129
|
+
prefix = [nil] if options.style == :justified
|
113
130
|
end
|
114
|
-
|
131
|
+
csv_writer << []
|
115
132
|
end
|
116
133
|
end
|
117
134
|
|