reportbuilder 0.2.0 → 1.0.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.
@@ -9,20 +9,19 @@ class ReportBuilder
9
9
  @out=""
10
10
  end
11
11
  def parse
12
- @out="Report: #{@builder.name}\n"
12
+ @out="#{@builder.name}\n" unless @builder.no_title
13
13
  parse_cycle(@builder)
14
- @out << "\n"
15
14
  end
16
- def add_text(t)
17
- ws=" "*parse_level*2
15
+ def text(t)
16
+ ws=" "*((parse_level-1)*2)
18
17
  @out << ws << t << "\n"
19
18
  end
20
- def add_preformatted(t)
21
- @out << t
19
+ def preformatted(t)
20
+ @out << t << "\n"
22
21
  end
23
- def add_html(t)
22
+ def html(t)
24
23
  # Nothing printed
25
24
  end
26
25
  end
27
26
  end
28
- end
27
+ end
@@ -1,4 +1,5 @@
1
- # Creates a Section
1
+ # Creates an Image
2
+ #
2
3
  class ReportBuilder::Image
3
4
  @@n=1
4
5
  attr_reader :name
@@ -20,12 +21,12 @@ class ReportBuilder::Image
20
21
  @filename=filename
21
22
  end
22
23
  # Based on http://rubyquiz.com/quiz50.html
23
- def to_reportbuilder_text(generator)
24
+ def report_building_text(generator)
24
25
  require 'RMagick'
25
-
26
-
26
+
27
+
27
28
  img = Magick::Image.read(@filename).first
28
-
29
+
29
30
  # Resize too-large images. The resulting image is going to be
30
31
  # about twice the size of the input, so if the original image is too
31
32
  # large we need to make it smaller so the ASCII version won't be too
@@ -38,7 +39,7 @@ class ReportBuilder::Image
38
39
  img.change_geometry('320x320>') do |cols, rows|
39
40
  img.resize!(cols, rows) if cols != img.columns || rows != img.rows
40
41
  end
41
-
42
+
42
43
  # Compute the image size in ASCII "pixels" and resize the image to have
43
44
  # those dimensions. The resulting image does not have the same aspect
44
45
  # ratio as the original, but since our "pixels" are twice as tall as
@@ -46,10 +47,10 @@ class ReportBuilder::Image
46
47
  pr = img.rows / @options[:font_rows]
47
48
  pc = img.columns / @options[:font_cols]
48
49
  img.resize!(pc, pr)
49
-
50
+
50
51
  img = img.quantize(@options[:chars].size, Magick::GRAYColorspace)
51
52
  img = img.normalize
52
-
53
+
53
54
  out=""
54
55
  # Draw the image surrounded by a border. The `view' method is slow but
55
56
  # it makes it easy to address individual pixels. In grayscale images,
@@ -62,17 +63,24 @@ class ReportBuilder::Image
62
63
  pr.times do |i|
63
64
  out+= '|'
64
65
  pc.times do |j|
65
- out+= @options[:chars][view[i][j].red / (2**16/@options[:chars].size)]
66
+ out+= @options[:chars][view[i][j].red / (2**16/@options[:chars].size)]
66
67
  end
67
68
  out+= '|'+"\n"
68
69
  end
69
70
  end
70
71
  out+= border
71
- generator.add_raw(out)
72
+ generator.preformatted(out)
72
73
  end
73
-
74
- def to_reportbuilder_html(generator)
75
- src=generator.add_image(@filename)
76
- generator.add_raw("<img src='#{src}' alt='#{@options[:alt]}' />")
74
+
75
+ def report_building_html(generator)
76
+ basedir=generator.directory+"/images"
77
+ out=basedir+"/"+File.basename(@filename)
78
+ if(File.exists? @filename)
79
+ if !File.exists? out
80
+ FileUtils.mkdir_p basedir
81
+ FileUtils.cp @filename, out
82
+ end
83
+ end
84
+ generator.html("<img src='images/#{File.basename(@filename)}' alt='#{@options[:alt]}' />")
77
85
  end
78
86
  end
@@ -1,16 +1,22 @@
1
- # Creates a Section
1
+ # Creates a Section.
2
+ # A section have a name and contains other elements.
3
+ # Sections could be nested inside anothers
4
+
2
5
  class ReportBuilder::Section
3
6
  @@n=1
4
7
  attr_reader :parent, :elements, :name
5
- def initialize(options={})
8
+ def initialize(options=Hash.new, &block)
6
9
  if !options.has_key? :name
7
- @name="Section #{@nn}"
8
- @nn+=1
10
+ @name="Section #{@@n}"
11
+ @@n+=1
9
12
  else
10
13
  @name=options[:name]
11
14
  end
12
15
  @parent = nil
13
16
  @elements = []
17
+ if block
18
+ add(block)
19
+ end
14
20
  end
15
21
  def parent=(sect)
16
22
  if sect.is_a? ReportBuilder::Section
@@ -19,20 +25,20 @@ class ReportBuilder::Section
19
25
  raise ArgumentError("Parent should be a Section")
20
26
  end
21
27
  end
22
-
23
- def to_reportbuilder_text(generator)
24
- generator.add_text(("="*generator.parse_level)+" "+name)
28
+
29
+ def report_building_text(generator)
30
+ generator.text(("="*generator.parse_level)+" "+name)
25
31
  generator.parse_cycle(self)
26
32
  end
27
-
28
- def to_reportbuilder_html(generator)
33
+
34
+ def report_building_html(generator)
29
35
  htag="h#{generator.parse_level+1}"
30
- anchor=generator.add_toc_entry(name)
31
- generator.add_html "<div class='section'><#{htag}>#{name}</#{htag}><a name='#{anchor}'></a>"
36
+ anchor=generator.toc_entry(name)
37
+ generator.html "<div class='section'><#{htag}>#{name}</#{htag}><a name='#{anchor}'></a>"
32
38
  generator.parse_cycle(self)
33
- generator.add_html "</div>"
39
+ generator.html "</div>"
34
40
  end
35
-
41
+
36
42
  def add(element)
37
43
  if element.is_a? ReportBuilder::Section
38
44
  element.parent=self
@@ -2,11 +2,11 @@ class ReportBuilder
2
2
  # Creates a table.
3
3
  # Use:
4
4
  # table=ReportBuilder::Table.new(:header =>["id","city","name","code1","code2"])
5
- # table.add_row([1, Table.rowspan("New York",3), "Ringo", Table.colspan("no code",2),nil])
6
- # table.add_row([2, nil,"John", "ab-1","ab-2"])
7
- # table.add_row([3, nil,"Paul", "ab-3"])
8
- # table.add_hr
9
- # table.add_row([4, "London","George", Table.colspan("ab-4",2),nil])
5
+ # table.row([1, Table.rowspan("New York",3), "Ringo", Table.colspan("no code",2),nil])
6
+ # table.row([2, nil,"John", "ab-1","ab-2"])
7
+ # table.row([3, nil,"Paul", "ab-3"])
8
+ # table.hr
9
+ # table.row([4, "London","George", Table.colspan("ab-4",2),nil])
10
10
  # puts table
11
11
  # ==>
12
12
  # -----------------------------------------
@@ -20,7 +20,7 @@ class ReportBuilder
20
20
  # -----------------------------------------
21
21
  class Table
22
22
  @@n=1 # :nodoc:
23
-
23
+
24
24
  DEFAULT_OPTIONS={
25
25
  :header => [],
26
26
  :name => nil
@@ -35,7 +35,7 @@ class ReportBuilder
35
35
  # Options: :name, :header
36
36
  # Use:
37
37
  # table=ReportBuilder::Table.new(:header =>["var1","var2"])
38
- def initialize(opts=Hash.new)
38
+ def initialize(opts=Hash.new, &block)
39
39
  raise ArgumentError,"opts should be a Hash" if !opts.is_a? Hash
40
40
  opts=DEFAULT_OPTIONS.merge opts
41
41
  if opts[:name].nil?
@@ -47,18 +47,21 @@ class ReportBuilder
47
47
  @header=opts[:header]
48
48
  @rows=[]
49
49
  @max_cols=[]
50
+ if block
51
+ block.arity<1 ? self.instance_eval(&block) : block.call(self)
52
+ end
50
53
  end
51
54
  # Adds a row
52
55
  # table.add_row(%w{1 2})
53
- def add_row(row)
56
+ def row(row)
54
57
  @rows.push(row)
55
58
  end
56
59
  # Adds a horizontal rule
57
60
  # table.add_hr
58
- def add_hr
61
+ def hr
59
62
  @rows.push(:hr)
60
63
  end
61
- alias_method :add_horizontal_line, :add_hr
64
+ alias_method :horizontal_line, :hr
62
65
  # Adds a rowspan on a cell
63
66
  # table.add_row(["a",table.rowspan("b",2)])
64
67
  def rowspan(data,n)
@@ -66,72 +69,76 @@ class ReportBuilder
66
69
  end
67
70
  # Adds a colspan on a cell
68
71
  # table.add_row(["a",table.colspan("b",2)])
69
-
72
+
70
73
  def colspan(data,n)
71
74
  Colspan.new(data,n)
72
75
  end
73
76
  def calculate_widths # :nodoc:
74
- @max_cols=[]
75
- rows_cal=[header]+@rows
76
- rows_cal.each{|row|
77
- next if row==:hr
78
- row.each_index{|i|
77
+ @max_cols=[]
78
+ rows_cal=[header]+@rows
79
+ rows_cal.each{|row|
80
+ next if row==:hr
81
+ row.each_index{|i|
79
82
  if row[i].nil?
80
- next
83
+ next
81
84
  elsif row[i].is_a? Colspan
82
- size_total=row[i].data.to_s.size
83
- size_per_column=(size_total / row[i].cols)+1
84
- for mi in i...i+row[i].cols
85
- @max_cols[mi] = size_per_column if @max_cols[mi].nil? or @max_cols[mi]<size_per_column
86
- end
85
+ size_total=row[i].data.to_s.size
86
+ size_per_column=(size_total / row[i].cols)+1
87
+ for mi in i...i+row[i].cols
88
+ @max_cols[mi] = size_per_column if @max_cols[mi].nil? or @max_cols[mi]<size_per_column
89
+ end
87
90
  elsif row[i].is_a? Rowspan
88
- size=row[i].data.to_s.size
89
- @max_cols[i]= size if @max_cols[i].nil? or @max_cols[i] < size
91
+ size=row[i].data.to_s.size
92
+ @max_cols[i]= size if @max_cols[i].nil? or @max_cols[i] < size
90
93
  else
91
-
92
- size=row[i].to_s.size
93
- @max_cols[i]= size if @max_cols[i].nil? or @max_cols[i] < size
94
+
95
+ size=row[i].to_s.size
96
+ @max_cols[i]= size if @max_cols[i].nil? or @max_cols[i] < size
94
97
  end
98
+ }
95
99
  }
96
- }
97
100
  end
98
- def to_reportbuilder_text(generator)
101
+ def report_building_text(generator)
99
102
  require 'reportbuilder/table/textgenerator'
100
103
  table_generator=ReportBuilder::Table::TextGenerator.new( generator, self)
101
104
  table_generator.generate
102
105
  end
103
- def to_reportbuilder_html(generator)
106
+ def report_building_html(generator)
104
107
  require 'reportbuilder/table/htmlgenerator'
105
108
  table_generator=ReportBuilder::Table::HtmlGenerator.new(generator, self)
106
109
  table_generator.generate
107
110
  end
108
111
 
109
112
  def total_width # :nodoc:
110
- @max_cols.inject(0){|a,v| a+(v+3)}+1
113
+ if @max_cols.size>0
114
+ @max_cols.inject(0){|a,v| a+(v+3)}+1
115
+ else
116
+ 0
117
+ end
111
118
  end
112
- ######################
113
- # INTERNAL CLASSES #
114
- ######################
115
-
119
+ ######################
120
+ # INTERNAL CLASSES #
121
+ ######################
122
+
116
123
  class Rowspan # :nodoc:
117
124
  attr_accessor :data, :rows
118
125
  def initialize(data,rows)
119
- @data=data
120
- @rows=rows
126
+ @data=data
127
+ @rows=rows
121
128
  end
122
129
  def to_s
123
- @data.to_s
130
+ @data.to_s
124
131
  end
125
132
  end
126
-
133
+
127
134
  class Colspan # :nodoc:
128
135
  attr_accessor :data, :cols
129
136
  def initialize(data,cols)
130
- @data=data
131
- @cols=cols
137
+ @data=data
138
+ @cols=cols
132
139
  end
133
140
  def to_s
134
- @data.to_s
141
+ @data.to_s
135
142
  end
136
143
  end
137
144
  end
@@ -1,17 +1,17 @@
1
1
  class ReportBuilder
2
2
  class Table
3
3
  class HtmlGenerator < ElementGenerator
4
- def generate()
5
- t=@element
6
- anchor=@generator.add_table_entry(t.name)
7
- out="<a name='#{anchor}'></a><table><caption>#{t.name}</caption>"
8
- @rowspans=[]
9
- if t.header.size>0
10
- out+="<thead>"+parse_row(t,t.header,"th")+"</thead>\n"
11
- end
12
- out+="<tbody>\n"
13
- next_class=""
14
- t.rows.each{|row|
4
+ def generate()
5
+ t=@element
6
+ anchor=@generator.table_entry(t.name)
7
+ out="<a name='#{anchor}'></a><table><caption>#{t.name}</caption>"
8
+ @rowspans=[]
9
+ if t.header.size>0
10
+ out+="<thead>"+parse_row(t,t.header,"th")+"</thead>\n"
11
+ end
12
+ out+="<tbody>\n"
13
+ next_class=""
14
+ t.rows.each{|row|
15
15
  if row==:hr
16
16
  next_class="top"
17
17
  else
@@ -19,32 +19,32 @@ class ReportBuilder
19
19
  out+="<tr#{class_tag}>"+parse_row(t,row)+"</tr>\n"
20
20
  next_class=""
21
21
  end
22
- }
23
- out+="</tbody>\n</table>\n"
24
- @generator.add_html(out)
25
- end
26
- def parse_row(t,row,tag="td")
27
- row_ary=[]
28
- colspan_i=0
29
- row.each_index do |i|
30
- if !@rowspans[i].nil? and @rowspans[i]>0
31
- @rowspans[i]-=1
32
- elsif colspan_i>0
33
- colspan_i-=1
34
- elsif row[i].is_a? Table::Colspan
35
- row_ary.push(sprintf("<%s colspan=\"%d\">%s</%s>",tag, row[i].cols, row[i].data,tag))
36
- colspan_i=row[i].cols-1
37
- elsif row[i].nil?
38
- row_ary.push("<#{tag}></#{tag}>")
39
- elsif row[i].is_a? Table::Rowspan
40
- row_ary.push(sprintf("<%s rowspan=\"%d\">%s</%s>", tag, row[i].rows, row[i].data, tag))
41
- @rowspans[i]=row[i].rows-1
42
- else
43
- row_ary.push("<#{tag}>#{row[i]}</#{tag}>")
44
- end
22
+ }
23
+ out+="</tbody>\n</table>\n"
24
+ @generator.html(out)
25
+ end
26
+ def parse_row(t,row,tag="td")
27
+ row_ary=[]
28
+ colspan_i=0
29
+ row.each_index do |i|
30
+ if !@rowspans[i].nil? and @rowspans[i]>0
31
+ @rowspans[i]-=1
32
+ elsif colspan_i>0
33
+ colspan_i-=1
34
+ elsif row[i].is_a? Table::Colspan
35
+ row_ary.push(sprintf("<%s colspan=\"%d\">%s</%s>",tag, row[i].cols, row[i].data,tag))
36
+ colspan_i=row[i].cols-1
37
+ elsif row[i].nil?
38
+ row_ary.push("<#{tag}></#{tag}>")
39
+ elsif row[i].is_a? Table::Rowspan
40
+ row_ary.push(sprintf("<%s rowspan=\"%d\">%s</%s>", tag, row[i].rows, row[i].data, tag))
41
+ @rowspans[i]=row[i].rows-1
42
+ else
43
+ row_ary.push("<#{tag}>#{row[i]}</#{tag}>")
45
44
  end
46
- row_ary.join("")
47
45
  end
46
+ row_ary.join("")
47
+ end
48
48
  end
49
49
  end
50
50
  end
@@ -1,26 +1,28 @@
1
1
  class ReportBuilder
2
2
  class Table
3
3
  class TextGenerator < ElementGenerator
4
-
4
+
5
5
  def generate()
6
6
  t=@element
7
7
  t.calculate_widths
8
8
  total_width=t.total_width
9
- out="Table: #{t.name}\n"
10
- if t.header.size>0
11
- out+=parse_hr(total_width)+"\n"
12
- out+=parse_row(t,t.header)+"\n"
13
- out+=parse_hr(total_width)+"\n"
14
- end
15
- t.rows.each do |row|
16
- if row==:hr
9
+ out="#{t.name}\n"
10
+ if total_width>0
11
+ if t.header.size>0
12
+ out+=parse_hr(total_width)+"\n"
13
+ out+=parse_row(t,t.header)+"\n"
17
14
  out+=parse_hr(total_width)+"\n"
18
- else
19
- out+=parse_row(t,row)+"\n"
20
15
  end
16
+ t.rows.each do |row|
17
+ if row==:hr
18
+ out+=parse_hr(total_width)+"\n"
19
+ else
20
+ out+=parse_row(t,row)+"\n"
21
+ end
22
+ end
23
+ out+=parse_hr(total_width)+"\n"
21
24
  end
22
- out+=parse_hr(total_width)+"\n"
23
- @generator.add_text(out)
25
+ @generator.text(out)
24
26
  end
25
27
  # Parse a row
26
28
  def parse_row(t,row)
@@ -48,6 +50,6 @@ class ReportBuilder
48
50
  def parse_hr(l)
49
51
  "-"*l
50
52
  end
51
- end
52
53
  end
54
+ end
53
55
  end