ruport 1.6.3 → 1.8.0
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/CHANGELOG.md +38 -0
- data/HACKING +1 -17
- data/README.md +97 -0
- data/Rakefile +9 -50
- 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/examples/row_renderer.rb +1 -1
- data/examples/simple_pdf_lines.rb +1 -1
- data/examples/trac_ticket_status.rb +1 -1
- data/lib/ruport/controller.rb +17 -21
- data/lib/ruport/data/feeder.rb +2 -2
- data/lib/ruport/data/grouping.rb +8 -8
- data/lib/ruport/data/record.rb +4 -4
- data/lib/ruport/data/table.rb +318 -206
- data/lib/ruport/formatter/csv.rb +6 -7
- data/lib/ruport/formatter/html.rb +13 -11
- data/lib/ruport/formatter/markdown.rb +105 -0
- data/lib/ruport/formatter/prawn_pdf.rb +159 -0
- data/lib/ruport/formatter/template.rb +1 -1
- data/lib/ruport/formatter/text.rb +1 -1
- data/lib/ruport/formatter.rb +54 -54
- data/lib/ruport/version.rb +1 -1
- data/lib/ruport.rb +7 -23
- data/test/controller_test.rb +201 -225
- data/test/csv_formatter_test.rb +36 -36
- data/test/data_feeder_test.rb +64 -64
- data/test/expected_outputs/prawn_pdf_formatter/pdf_basic.pdf.test +265 -0
- data/test/grouping_test.rb +103 -102
- data/test/helpers.rb +29 -10
- data/test/html_formatter_test.rb +46 -46
- data/test/markdown_formatter_test.rb +142 -0
- data/test/prawn_pdf_formatter_test.rb +108 -0
- data/test/record_test.rb +91 -91
- data/test/samples/sales.csv +21 -0
- data/test/table_pivot_test.rb +77 -26
- data/test/table_test.rb +376 -354
- data/test/template_test.rb +13 -13
- data/test/text_formatter_test.rb +52 -52
- data/util/bench/data/table/bench_column_manip.rb +0 -1
- data/util/bench/data/table/bench_dup.rb +0 -1
- data/util/bench/data/table/bench_init.rb +1 -2
- data/util/bench/data/table/bench_manip.rb +0 -1
- data/util/bench/formatter/bench_csv.rb +0 -1
- data/util/bench/formatter/bench_html.rb +0 -1
- data/util/bench/formatter/bench_pdf.rb +0 -1
- data/util/bench/formatter/bench_text.rb +0 -1
- metadata +131 -82
- data/README +0 -114
- data/lib/ruport/formatter/pdf.rb +0 -591
- data/test/pdf_formatter_test.rb +0 -354
data/lib/ruport/formatter/csv.rb
CHANGED
@@ -14,16 +14,15 @@
|
|
14
14
|
module Ruport
|
15
15
|
|
16
16
|
# This formatter implements the CSV format for Ruport's Row, Table, Group
|
17
|
-
# and Grouping controllers.
|
18
|
-
# James Edward Gray II's FasterCSV.
|
17
|
+
# and Grouping controllers.
|
19
18
|
#
|
20
19
|
# === Rendering Options
|
21
20
|
#
|
22
21
|
# <tt>:style</tt> Used for grouping (:inline,:justified,:raw)
|
23
22
|
#
|
24
|
-
# <tt>:format_options</tt> A hash of
|
23
|
+
# <tt>:format_options</tt> A hash of CSV options
|
25
24
|
#
|
26
|
-
# <tt>:formatter</tt> An existing
|
25
|
+
# <tt>:formatter</tt> An existing CSV object to write to
|
27
26
|
#
|
28
27
|
# <tt>:show_table_headers</tt> True by default
|
29
28
|
#
|
@@ -35,7 +34,7 @@ module Ruport
|
|
35
34
|
Controller::Group, Controller::Grouping ]
|
36
35
|
|
37
36
|
def initialize
|
38
|
-
require "
|
37
|
+
require "csv"
|
39
38
|
end
|
40
39
|
|
41
40
|
attr_writer :csv_writer
|
@@ -49,14 +48,14 @@ module Ruport
|
|
49
48
|
options.format_options ||= template.format_options
|
50
49
|
end
|
51
50
|
|
52
|
-
# Returns the current
|
51
|
+
# Returns the current CSV object or creates a new one if it has not
|
53
52
|
# been set yet. Note that FCSV(sig) has a cache and returns the *same*
|
54
53
|
# FCSV object if writing to the same underlying output with the same
|
55
54
|
# options.
|
56
55
|
#
|
57
56
|
def csv_writer
|
58
57
|
@csv_writer ||= options.formatter ||
|
59
|
-
|
58
|
+
::CSV.instance(output, **(options.format_options || {}))
|
60
59
|
end
|
61
60
|
|
62
61
|
# Generates table header by turning column_names into a CSV row.
|
@@ -40,12 +40,7 @@ module Ruport
|
|
40
40
|
# This method does not do anything if options.show_table_headers is false
|
41
41
|
# or the Data::Table has no column names.
|
42
42
|
def build_table_header
|
43
|
-
output <<
|
44
|
-
unless data.column_names.empty? || !options.show_table_headers
|
45
|
-
output << "\t\t<tr>\n\t\t\t<th>" +
|
46
|
-
data.column_names.join("</th>\n\t\t\t<th>") +
|
47
|
-
"</th>\n\t\t</tr>\n"
|
48
|
-
end
|
43
|
+
output << build_header(options.show_table_headers ? data.column_names : nil)
|
49
44
|
end
|
50
45
|
|
51
46
|
# Uses the Row controller to build up the table body.
|
@@ -119,12 +114,19 @@ module Ruport
|
|
119
114
|
end
|
120
115
|
|
121
116
|
private
|
122
|
-
|
117
|
+
|
118
|
+
def build_header(columns)
|
119
|
+
if !columns || columns.empty?
|
120
|
+
"\t<table>\n"
|
121
|
+
else
|
122
|
+
"\t<table>\n\t\t<thead>\n\t\t<tr>\n\t\t\t<th>" +
|
123
|
+
columns.join("</th>\n\t\t\t<th>") +
|
124
|
+
"</th>\n\t\t</tr>\n\t\t</thead>\n"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
123
128
|
def render_justified_grouping
|
124
|
-
output <<
|
125
|
-
"#{data.grouped_by}</th>\n\t\t\t<th>" +
|
126
|
-
grouping_columns.join("</th>\n\t\t\t<th>") +
|
127
|
-
"</th>\n\t\t</tr>\n"
|
129
|
+
output << build_header(options.show_group_headers ? ([data.grouped_by] + grouping_columns) : nil)
|
128
130
|
data.each do |name, group|
|
129
131
|
group.each_with_index do |row, i|
|
130
132
|
output << "\t\t<tr>\n\t\t\t"
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ruport
|
4
|
+
# This class produces Markdown table output from Ruport::Table data.
|
5
|
+
#
|
6
|
+
# === Rendering Options
|
7
|
+
# <tt>:alignment:</tt> Default alignment for all columns.
|
8
|
+
# Allowed values are :left, :center and :right. Default is :left.
|
9
|
+
#
|
10
|
+
# <tt>:column_alignments:</tt> Alignments for specific columns.
|
11
|
+
# You can configure alignments by using
|
12
|
+
# Hash (key: column name, value: alignment)
|
13
|
+
class Formatter::MarkDown < Formatter
|
14
|
+
renders :markdown, for: [Controller::Table]
|
15
|
+
|
16
|
+
# Hook for setting available options using a template.
|
17
|
+
def apply_template
|
18
|
+
apply_table_format_template(template.table)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Uses the column names from the given Data::Table to generate
|
22
|
+
# a table header.
|
23
|
+
# If no column names are given, first row will be
|
24
|
+
# treated as table header.
|
25
|
+
def build_table_header
|
26
|
+
names = column_names(data)
|
27
|
+
build_md_row(output, names)
|
28
|
+
build_md_row(output, alignment_strings(names))
|
29
|
+
end
|
30
|
+
|
31
|
+
# Generates body of Markdown table data.
|
32
|
+
# Following characters will be replaced as escape.
|
33
|
+
#
|
34
|
+
# * | -> |
|
35
|
+
# * newline code(\\n) -> \<br>
|
36
|
+
def build_table_body
|
37
|
+
body =
|
38
|
+
if data.column_names && !data.column_names.empty?
|
39
|
+
data
|
40
|
+
else
|
41
|
+
data[1..-1]
|
42
|
+
end
|
43
|
+
body.each { |row| build_md_row(output, row) }
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def column_names(data)
|
49
|
+
if data.column_names && !data.column_names.empty?
|
50
|
+
data.column_names
|
51
|
+
else
|
52
|
+
data[0]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def build_md_row(output, row)
|
57
|
+
output << "|"
|
58
|
+
output << row.to_a.map { |cell| escape(cell.to_s.dup) }.join('|')
|
59
|
+
output << "|\n"
|
60
|
+
end
|
61
|
+
|
62
|
+
def escape(cell)
|
63
|
+
cell.gsub!("|", "|")
|
64
|
+
cell.gsub!("\n", "<br>")
|
65
|
+
cell
|
66
|
+
end
|
67
|
+
|
68
|
+
def alignment_strings(column_names)
|
69
|
+
column_names.map(&method(:alignment_string))
|
70
|
+
end
|
71
|
+
|
72
|
+
def alignment_string(column_name)
|
73
|
+
case column_alignment(column_name)
|
74
|
+
when :right
|
75
|
+
"--:"
|
76
|
+
when :center
|
77
|
+
":-:"
|
78
|
+
else
|
79
|
+
":--"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def column_alignment(column_name)
|
84
|
+
if options.column_alignments && options.column_alignments.key?(column_name)
|
85
|
+
options.column_alignments[column_name]
|
86
|
+
elsif options.alignment
|
87
|
+
options.alignment
|
88
|
+
else
|
89
|
+
:left
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def apply_table_format_template(template)
|
94
|
+
template = (template || {}).merge(options.table_format || {})
|
95
|
+
options.alignment ||= template[:alignment]
|
96
|
+
options.column_alignments =
|
97
|
+
merget_column_alignments(options, template)
|
98
|
+
end
|
99
|
+
|
100
|
+
def merget_column_alignments(options, template)
|
101
|
+
(template[:column_alignments] || {})
|
102
|
+
.merge(options.column_alignments || {})
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,159 @@
|
|
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_writer :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/table'
|
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={}, &block)
|
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 = format_opts
|
37
|
+
end
|
38
|
+
|
39
|
+
pdf.table(table_array, opt, &block)
|
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(&block)
|
52
|
+
draw_table(data, &block)
|
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(&block)
|
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, &block
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Hook for setting available options using a template. See the template
|
73
|
+
# documentation for the available options and their format.
|
74
|
+
def apply_template
|
75
|
+
apply_page_format_template(template.page)
|
76
|
+
apply_text_format_template(template.text)
|
77
|
+
apply_table_format_template(template.table)
|
78
|
+
apply_column_format_template(template.column)
|
79
|
+
apply_heading_format_template(template.heading)
|
80
|
+
apply_grouping_format_template(template.grouping)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def apply_page_format_template(t)
|
86
|
+
options.pdf_format ||= {}
|
87
|
+
t = (t || {}).merge(options.page_format || {})
|
88
|
+
options.pdf_format[:page_size] ||= t[:size]
|
89
|
+
options.pdf_format[:page_layout] ||= t[:layout]
|
90
|
+
end
|
91
|
+
|
92
|
+
def apply_text_format_template(t)
|
93
|
+
t = (t || {}).merge(options.text_format || {})
|
94
|
+
options.text_format = t unless t.empty?
|
95
|
+
end
|
96
|
+
|
97
|
+
def apply_table_format_template(t)
|
98
|
+
t = (t || {}).merge(options.table_format || {})
|
99
|
+
options.table_format = t unless t.empty?
|
100
|
+
end
|
101
|
+
|
102
|
+
def apply_column_format_template(t)
|
103
|
+
t = (t || {}).merge(options.column_format || {})
|
104
|
+
column_opts = {}
|
105
|
+
column_opts.merge!(:justification => t[:alignment]) if t[:alignment]
|
106
|
+
column_opts.merge!(:width => t[:width]) if t[:width]
|
107
|
+
unless column_opts.empty?
|
108
|
+
if options.table_format
|
109
|
+
if options.table_format[:column_options]
|
110
|
+
options.table_format[:column_options] =
|
111
|
+
column_opts.merge(options.table_format[:column_options])
|
112
|
+
else
|
113
|
+
options.table_format.merge!(:column_options => column_opts)
|
114
|
+
end
|
115
|
+
else
|
116
|
+
options.table_format = { :column_options => column_opts }
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def apply_heading_format_template(t)
|
122
|
+
t = (t || {}).merge(options.heading_format || {})
|
123
|
+
heading_opts = {}
|
124
|
+
heading_opts.merge!(:justification => t[:alignment]) if t[:alignment]
|
125
|
+
heading_opts.merge!(:bold => t[:bold]) unless t[:bold].nil?
|
126
|
+
heading_opts.merge!(:title => t[:title]) if t[:title]
|
127
|
+
unless heading_opts.empty?
|
128
|
+
if options.table_format
|
129
|
+
if options.table_format[:column_options]
|
130
|
+
if options.table_format[:column_options][:heading]
|
131
|
+
options.table_format[:column_options][:heading] =
|
132
|
+
heading_opts.merge(
|
133
|
+
options.table_format[:column_options][:heading]
|
134
|
+
)
|
135
|
+
else
|
136
|
+
options.table_format[:column_options].merge!(
|
137
|
+
:heading => heading_opts
|
138
|
+
)
|
139
|
+
end
|
140
|
+
else
|
141
|
+
options.table_format.merge!(
|
142
|
+
:column_options => { :heading => heading_opts }
|
143
|
+
)
|
144
|
+
end
|
145
|
+
else
|
146
|
+
options.table_format = {
|
147
|
+
:column_options => { :heading => heading_opts }
|
148
|
+
}
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def apply_grouping_format_template(t)
|
154
|
+
t = (t || {}).merge(options.grouping_format || {})
|
155
|
+
options.style ||= t[:style]
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
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
|
|
@@ -110,7 +110,7 @@ module Ruport
|
|
110
110
|
def build_row(data = self.data)
|
111
111
|
max_col_widths_for_row(data) unless options.max_col_width
|
112
112
|
|
113
|
-
data.enum_for(:each_with_index).inject(line=[]) { |
|
113
|
+
data.enum_for(:each_with_index).inject(line=[]) { |_s,e|
|
114
114
|
field,index = e
|
115
115
|
if options.alignment.eql? :center
|
116
116
|
line << field.to_s.center(options.max_col_width[index])
|
data/lib/ruport/formatter.rb
CHANGED
@@ -1,73 +1,73 @@
|
|
1
|
-
# Ruport : Extensible Reporting System
|
1
|
+
# Ruport : Extensible Reporting System
|
2
2
|
#
|
3
3
|
# formatter.rb provides a generalized base class for creating ruport formatters.
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Created By Gregory Brown
|
6
|
-
# Copyright (C) December 2006, All Rights Reserved.
|
6
|
+
# Copyright (C) December 2006, All Rights Reserved.
|
7
7
|
#
|
8
8
|
# This is free software distributed under the same terms as Ruby 1.8
|
9
9
|
# See LICENSE and COPYING for details.
|
10
|
-
module Ruport
|
10
|
+
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 Controller classes.
|
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
|
18
18
|
# access, and basic output wrapping.
|
19
19
|
#
|
20
20
|
# The following example should provide a general idea of how formatters
|
21
|
-
# work, but see the built in formatters for reference implementations.
|
22
|
-
#
|
21
|
+
# work, but see the built in formatters for reference implementations.
|
22
|
+
#
|
23
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
27
|
# class ReverseController < Ruport::Controller
|
28
|
-
# stage :reversed_header, :reversed_body
|
28
|
+
# stage :reversed_header, :reversed_body
|
29
29
|
# end
|
30
|
-
#
|
31
|
-
# class ReversedText < Ruport::Formatter
|
32
|
-
#
|
30
|
+
#
|
31
|
+
# class ReversedText < Ruport::Formatter
|
32
|
+
#
|
33
33
|
# # Hooks formatter up to controller
|
34
|
-
# renders :txt, :for => ReverseController
|
35
|
-
#
|
34
|
+
# renders :txt, :for => ReverseController
|
35
|
+
#
|
36
36
|
# # Implements ReverseController's :reversed_header hook
|
37
|
-
# # but can be used by any controller
|
38
|
-
# def build_reversed_header
|
37
|
+
# # but can be used by any controller
|
38
|
+
# def build_reversed_header
|
39
39
|
# output << "#{options.header_text}\n"
|
40
40
|
# output << "The reversed text will follow\n"
|
41
|
-
# end
|
42
|
-
#
|
41
|
+
# end
|
42
|
+
#
|
43
43
|
# # Implements ReverseController's :reversed_body hook
|
44
44
|
# # but can be used by any controller
|
45
45
|
# def build_reversed_body
|
46
46
|
# output << data.reverse << "\n"
|
47
|
-
# end
|
47
|
+
# end
|
48
48
|
#
|
49
|
-
# end
|
49
|
+
# end
|
50
50
|
#
|
51
51
|
# puts ReverseController.render_txt(:data => "apple",
|
52
52
|
# :header_text => "Hello Mike, Hello Joe!")
|
53
|
-
#
|
53
|
+
#
|
54
54
|
# -----
|
55
|
-
# OUTPUT:
|
56
|
-
#
|
55
|
+
# OUTPUT:
|
56
|
+
#
|
57
57
|
# Hello Mike, Hello Joe!
|
58
58
|
# The reversed text will follow
|
59
59
|
# elppa
|
60
|
-
#
|
60
|
+
#
|
61
61
|
class Formatter
|
62
|
-
|
62
|
+
|
63
63
|
# Provides shortcuts so that you can use Ruport's default rendering
|
64
|
-
# capabilities within your custom formatters
|
64
|
+
# capabilities within your custom formatters
|
65
65
|
#
|
66
66
|
module RenderingTools
|
67
67
|
# Uses Controller::Row to render the Row object with the
|
68
68
|
# given options.
|
69
69
|
#
|
70
|
-
# Sets the <tt>:io</tt> attribute by default to the existing
|
70
|
+
# Sets the <tt>:io</tt> attribute by default to the existing
|
71
71
|
# formatter's <tt>output</tt> object.
|
72
72
|
def render_row(row,options={},&block)
|
73
73
|
render_helper(Controller::Row,row,options,&block)
|
@@ -99,12 +99,12 @@ module Ruport
|
|
99
99
|
def render_grouping(grouping,options={},&block)
|
100
100
|
render_helper(Controller::Grouping,grouping,options,&block)
|
101
101
|
end
|
102
|
-
|
102
|
+
|
103
103
|
# Iterates through the data in the grouping and renders each group
|
104
104
|
# followed by a newline.
|
105
105
|
#
|
106
106
|
def render_inline_grouping(options={},&block)
|
107
|
-
data.each do |_,group|
|
107
|
+
data.each do |_,group|
|
108
108
|
render_group(group, options, &block)
|
109
109
|
output << "\n"
|
110
110
|
end
|
@@ -113,11 +113,10 @@ module Ruport
|
|
113
113
|
private
|
114
114
|
|
115
115
|
def render_helper(rend_klass, source_data,options={},&block)
|
116
|
-
options = {:data => source_data,
|
116
|
+
options = {:data => source_data,
|
117
117
|
:io => output,
|
118
|
-
:layout => false }.merge(options)
|
119
|
-
|
120
|
-
options[:io] = "" if self.class.kind_of?(Ruport::Formatter::PDF)
|
118
|
+
:layout => false }.merge(options)
|
119
|
+
|
121
120
|
rend_klass.render(format,options) do |rend|
|
122
121
|
block[rend] if block
|
123
122
|
end
|
@@ -126,13 +125,13 @@ module Ruport
|
|
126
125
|
end
|
127
126
|
|
128
127
|
include RenderingTools
|
129
|
-
|
128
|
+
|
130
129
|
# Set by the <tt>:data</tt> attribute from Controller#render
|
131
|
-
attr_reader :data
|
132
|
-
|
130
|
+
attr_reader :data
|
131
|
+
|
133
132
|
# Set automatically by Controller#render(format) or Controller#render_format
|
134
|
-
attr_accessor :format
|
135
|
-
|
133
|
+
attr_accessor :format
|
134
|
+
|
136
135
|
# Set automatically by Controller#render as a Controller::Options object built
|
137
136
|
# by the hash provided.
|
138
137
|
attr_writer :options
|
@@ -145,24 +144,24 @@ module Ruport
|
|
145
144
|
#
|
146
145
|
def self.renders(fmts,options={})
|
147
146
|
Array(fmts).each do |format|
|
148
|
-
Array(options[:for]).each do |o|
|
149
|
-
o.send(:add_format,self,format)
|
147
|
+
Array(options[:for]).each do |o|
|
148
|
+
o.send(:add_format,self,format)
|
150
149
|
formats << format unless formats.include?(format)
|
151
|
-
end
|
150
|
+
end
|
152
151
|
end
|
153
152
|
end
|
154
|
-
|
153
|
+
|
155
154
|
# Allows you to implement stages in your formatter using the
|
156
155
|
# following syntax:
|
157
156
|
#
|
158
|
-
# class ReversedText < Ruport::Formatter
|
157
|
+
# class ReversedText < Ruport::Formatter
|
159
158
|
# renders :txt, :for => ReverseController
|
160
|
-
#
|
159
|
+
#
|
161
160
|
# build :reversed_header do
|
162
161
|
# output << "#{options.header_text}\n"
|
163
162
|
# output << "The reversed text will follow\n"
|
164
163
|
# end
|
165
|
-
#
|
164
|
+
#
|
166
165
|
# build :reversed_body do
|
167
166
|
# output << data.reverse << "\n"
|
168
167
|
# end
|
@@ -171,12 +170,12 @@ module Ruport
|
|
171
170
|
def self.build(stage,&block)
|
172
171
|
define_method "build_#{stage}", &block
|
173
172
|
end
|
174
|
-
|
173
|
+
|
175
174
|
# Gives a list of formats registered for this formatter.
|
176
175
|
def self.formats
|
177
176
|
@formats ||= []
|
178
|
-
end
|
179
|
-
|
177
|
+
end
|
178
|
+
|
180
179
|
# Returns the template currently set for this formatter.
|
181
180
|
def template
|
182
181
|
Template[options.template] rescue nil || Template[:default]
|
@@ -191,7 +190,7 @@ module Ruport
|
|
191
190
|
# Provides a Controller::Options object for storing formatting options.
|
192
191
|
def options
|
193
192
|
@options ||= Controller::Options.new
|
194
|
-
end
|
193
|
+
end
|
195
194
|
|
196
195
|
# Sets the data object, making a local copy using #dup. This may have
|
197
196
|
# a significant overhead for large tables, so formatters which don't
|
@@ -204,24 +203,24 @@ module Ruport
|
|
204
203
|
def clear_output
|
205
204
|
@output.replace("")
|
206
205
|
end
|
207
|
-
|
206
|
+
|
208
207
|
# Saves the output to a file.
|
209
208
|
def save_output(filename)
|
210
209
|
File.open(filename,"w") {|f| f << output }
|
211
210
|
end
|
212
|
-
|
211
|
+
|
213
212
|
# Use to define that your formatter should save in binary format
|
214
213
|
def self.save_as_binary_file
|
215
214
|
define_method :save_output do |filename|
|
216
215
|
File.open(filename,"wb") {|f| f << output }
|
217
216
|
end
|
218
217
|
end
|
219
|
-
|
218
|
+
|
220
219
|
# Evaluates the string using ERB and returns the results.
|
221
220
|
#
|
222
221
|
# If <tt>:binding</tt> is specified, it will evaluate the template
|
223
222
|
# in that context.
|
224
|
-
def erb(string,options={})
|
223
|
+
def erb(string,options={})
|
225
224
|
require "erb"
|
226
225
|
if string =~ /(\.r\w+)|(\.erb)$/
|
227
226
|
ERB.new(File.read(string)).result(options[:binding]||binding)
|
@@ -245,10 +244,11 @@ module Ruport
|
|
245
244
|
end
|
246
245
|
end
|
247
246
|
end
|
248
|
-
end
|
247
|
+
end
|
249
248
|
|
250
249
|
require "ruport/formatter/template"
|
251
250
|
require "ruport/formatter/csv"
|
252
251
|
require "ruport/formatter/html"
|
253
252
|
require "ruport/formatter/text"
|
254
|
-
require "ruport/formatter/
|
253
|
+
require "ruport/formatter/prawn_pdf"
|
254
|
+
require "ruport/formatter/markdown"
|
data/lib/ruport/version.rb
CHANGED
data/lib/ruport.rb
CHANGED
@@ -10,18 +10,6 @@
|
|
10
10
|
# See LICENSE and COPYING for details
|
11
11
|
#
|
12
12
|
|
13
|
-
|
14
|
-
if RUBY_VERSION > "1.9"
|
15
|
-
require "csv"
|
16
|
-
unless defined? FCSV
|
17
|
-
class Object
|
18
|
-
FCSV = CSV
|
19
|
-
alias_method :FCSV, :CSV
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
|
25
13
|
module Ruport #:nodoc:#
|
26
14
|
class FormatterError < RuntimeError #:nodoc:
|
27
15
|
end
|
@@ -72,29 +60,26 @@ module Ruport #:nodoc:#
|
|
72
60
|
stdout_handle = m_GetStdHandle.call(0xFFFFFFF5)
|
73
61
|
|
74
62
|
m_GetConsoleScreenBufferInfo.call(stdout_handle, buf)
|
75
|
-
|
76
|
-
left, top, right, bottom, maxx, maxy = buf.unpack(format)
|
63
|
+
_bufx, _bufy, _curx, _cury, _wattr, left, top, right, bottom, _maxx, _maxy = buf.unpack(format)
|
77
64
|
return right - left + 1, bottom - top + 1
|
78
65
|
end
|
79
66
|
rescue LoadError # If we're not on Windows try...
|
80
67
|
# A Unix savvy method to fetch the console columns, and rows.
|
81
68
|
def terminal_size
|
82
69
|
size = if /solaris/ =~ RUBY_PLATFORM
|
83
|
-
output = `stty`
|
70
|
+
output = `stty 2>&1`
|
84
71
|
[output.match('columns = (\d+)')[1].to_i,
|
85
72
|
output.match('rows = (\d+)')[1].to_i]
|
86
73
|
else
|
87
|
-
`stty size`.split.map { |x| x.to_i }.reverse
|
74
|
+
`stty size 2>&1`.split.map { |x| x.to_i }.reverse
|
88
75
|
end
|
89
76
|
return $? == 0 ? size : [80,24]
|
90
77
|
end
|
91
|
-
|
92
|
-
end
|
78
|
+
end
|
93
79
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
80
|
+
def terminal_width
|
81
|
+
terminal_size.first
|
82
|
+
end
|
98
83
|
end
|
99
84
|
|
100
85
|
# quiets warnings for block
|
@@ -111,7 +96,6 @@ module Ruport #:nodoc:#
|
|
111
96
|
end
|
112
97
|
|
113
98
|
require "ruport/version"
|
114
|
-
require "enumerator"
|
115
99
|
require "ruport/controller"
|
116
100
|
require "ruport/data"
|
117
101
|
require "ruport/formatter"
|