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.
- data/History.txt +10 -0
 - data/README.txt +38 -10
 - data/Rakefile +1 -1
 - data/lib/reportbuilder.rb +93 -31
 - data/lib/reportbuilder/generator.rb +57 -18
 - data/lib/reportbuilder/generator/html.rb +46 -55
 - data/lib/reportbuilder/generator/text.rb +7 -8
 - data/lib/reportbuilder/image.rb +22 -14
 - data/lib/reportbuilder/section.rb +19 -13
 - data/lib/reportbuilder/table.rb +49 -42
 - data/lib/reportbuilder/table/htmlgenerator.rb +35 -35
 - data/lib/reportbuilder/table/textgenerator.rb +16 -14
 - data/test/test_html.rb +43 -22
 - data/test/test_image.rb +11 -10
 - data/test/test_reportbuilder.rb +70 -11
 - data/test/test_section.rb +60 -44
 - data/test/test_table.rb +52 -20
 - metadata +63 -11
 
    
        data/History.txt
    CHANGED
    
    | 
         @@ -1,3 +1,13 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            === 1.0.0 / 2009-03-22
         
     | 
| 
      
 2 
     | 
    
         
            +
            Change of API:
         
     | 
| 
      
 3 
     | 
    
         
            +
             * Deleted "add_" before methods
         
     | 
| 
      
 4 
     | 
    
         
            +
             * Massive use of block after functions, to allow easy creation of reports
         
     | 
| 
      
 5 
     | 
    
         
            +
            For example, you can create
         
     | 
| 
      
 6 
     | 
    
         
            +
                ReportBuilder.generate(:name=>"Report 1", :format=>:html) do
         
     | 
| 
      
 7 
     | 
    
         
            +
                    text("A paragraph")
         
     | 
| 
      
 8 
     | 
    
         
            +
                    preformatted("a pre statement")
         
     | 
| 
      
 9 
     | 
    
         
            +
                    
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
       1 
11 
     | 
    
         
             
            === 1.0.0 / 2009-08-12
         
     | 
| 
       2 
12 
     | 
    
         | 
| 
       3 
13 
     | 
    
         
             
            * 1 major enhancement
         
     | 
    
        data/README.txt
    CHANGED
    
    | 
         @@ -4,26 +4,54 @@ 
     | 
|
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            == DESCRIPTION:
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
            Report Abstract Interface. Creates text 
     | 
| 
      
 7 
     | 
    
         
            +
            Report Abstract Interface. Creates text and html output, based on a common framework.
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
            == FEATURES
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
            * One interface, multiple outputs
         
     | 
| 
      
 12 
     | 
    
         
            +
            * You have two interfaces:
         
     | 
| 
      
 13 
     | 
    
         
            +
              * Generic, based on adding objects to a ReportBuilder object
         
     | 
| 
      
 14 
     | 
    
         
            +
              * Fine tuning, directly operating on ReportBuilder::Generator interface
         
     | 
| 
       12 
15 
     | 
    
         | 
| 
       13 
16 
     | 
    
         
             
            == SYNOPSIS:
         
     | 
| 
       14 
17 
     | 
    
         | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
               
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
      
 18 
     | 
    
         
            +
            * Using generic ReportBuilder#add, every object will be parsed 
         
     | 
| 
      
 19 
     | 
    
         
            +
              using #report_building_FORMAT, #report_building or #to_s
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                require "reportbuilder"    
         
     | 
| 
      
 22 
     | 
    
         
            +
                rb=ReportBuilder.new
         
     | 
| 
      
 23 
     | 
    
         
            +
                rb.add(2) # Int#to_s used
         
     | 
| 
      
 24 
     | 
    
         
            +
                table=ReportBuilder::Table.new(:name=>"Table", :header=>%w{id name})
         
     | 
| 
      
 25 
     | 
    
         
            +
                table.row([1,"John"])
         
     | 
| 
      
 26 
     | 
    
         
            +
                rb.add(table) # table have a #report_building method
         
     | 
| 
      
 27 
     | 
    
         
            +
                rb.add("Another text") # used directly
         
     | 
| 
      
 28 
     | 
    
         
            +
                rb.name="Text output"
         
     | 
| 
      
 29 
     | 
    
         
            +
                puts rb.to_text
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            * Using a block, you can control directly the generator
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                require "reportbuilder"    
         
     | 
| 
      
 34 
     | 
    
         
            +
                rb=ReportBuilder.new do
         
     | 
| 
      
 35 
     | 
    
         
            +
                  text("2")
         
     | 
| 
      
 36 
     | 
    
         
            +
                  section(:name=>"Section 1") do
         
     | 
| 
      
 37 
     | 
    
         
            +
                    table(:name=>"Table", :header=>%w{id name}) do
         
     | 
| 
      
 38 
     | 
    
         
            +
                      row([1,"John"])
         
     | 
| 
      
 39 
     | 
    
         
            +
                    end
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
                  preformatted("Another Text")
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
                rb.name="Html output"
         
     | 
| 
      
 44 
     | 
    
         
            +
                puts rb.to_html
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            == DEVELOPERS
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            If you want to give support to your class, create a method called #report_building(g), which accept a ReportBuilder::Generator as argument. If you need fine control of output according to format, append the name of format, like #report_building_html, #report_building_text.
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            See ReportBuilder::Generator for API and ReportBuilder::Table, ReportBuilder::Image and ReportBuilder::Section for examples of implementation. Also, Statsample package object uses report_building on almost every class.
         
     | 
| 
       24 
51 
     | 
    
         | 
| 
       25 
52 
     | 
    
         
             
            == REQUIREMENTS:
         
     | 
| 
       26 
53 
     | 
    
         | 
| 
      
 54 
     | 
    
         
            +
            * RMagick, only to generate text output of images (see examples/image.rb)
         
     | 
| 
       27 
55 
     | 
    
         | 
| 
       28 
56 
     | 
    
         
             
            == INSTALL:
         
     | 
| 
       29 
57 
     | 
    
         | 
    
        data/Rakefile
    CHANGED
    
    | 
         @@ -11,7 +11,7 @@ Hoe.spec 'reportbuilder' do 
     | 
|
| 
       11 
11 
     | 
    
         
             
              self.rubyforge_name = 'ruby-statsample'
         
     | 
| 
       12 
12 
     | 
    
         
             
              self.developer('Claudio Bustos', 'clbustos_at_gmail.com')
         
     | 
| 
       13 
13 
     | 
    
         
             
              self.url = "http://rubyforge.org/projects/ruby-statsample/"
         
     | 
| 
       14 
     | 
    
         
            -
              
         
     | 
| 
      
 14 
     | 
    
         
            +
              self.extra_dev_deps << ["hpricot", "~>0.8"]
         
     | 
| 
       15 
15 
     | 
    
         
             
            end
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
17 
     | 
    
         
             
            # vim: syntax=ruby
         
     | 
    
        data/lib/reportbuilder.rb
    CHANGED
    
    | 
         @@ -2,55 +2,117 @@ require 'reportbuilder/table' 
     | 
|
| 
       2 
2 
     | 
    
         
             
            require 'reportbuilder/section'
         
     | 
| 
       3 
3 
     | 
    
         
             
            require 'reportbuilder/generator'
         
     | 
| 
       4 
4 
     | 
    
         
             
            require 'reportbuilder/image'
         
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
      
 5 
     | 
    
         
            +
            # = Report Abstract Interface.
         
     | 
| 
      
 6 
     | 
    
         
            +
            # Creates text and html output, based on a common framework.
         
     | 
| 
      
 7 
     | 
    
         
            +
            # == Use
         
     | 
| 
      
 8 
     | 
    
         
            +
            # 
         
     | 
| 
      
 9 
     | 
    
         
            +
            # 
         
     | 
| 
      
 10 
     | 
    
         
            +
            # * Using generic ReportBuilder#add, every object will be parsed using #report_building_FORMAT, #report_building or #to_s
         
     | 
| 
      
 11 
     | 
    
         
            +
            # 
         
     | 
| 
      
 12 
     | 
    
         
            +
            #  require "reportbuilder"    
         
     | 
| 
      
 13 
     | 
    
         
            +
            #  rb=ReportBuilder.new
         
     | 
| 
      
 14 
     | 
    
         
            +
            #  rb.add(2) #  Int#to_s used
         
     | 
| 
      
 15 
     | 
    
         
            +
            #  section=ReportBuilder::Section.new(:name=>"Section 1")
         
     | 
| 
      
 16 
     | 
    
         
            +
            #  table=ReportBuilder::Table.new(:name=>"Table", :header=>%w{id name})
         
     | 
| 
      
 17 
     | 
    
         
            +
            #  table.row([1,"John"])
         
     | 
| 
      
 18 
     | 
    
         
            +
            #  table.hr
         
     | 
| 
      
 19 
     | 
    
         
            +
            #  table.row([2,"Peter"])
         
     | 
| 
      
 20 
     | 
    
         
            +
            #  
         
     | 
| 
      
 21 
     | 
    
         
            +
            #  section.add(table) #  Section is a container for other methods
         
     | 
| 
      
 22 
     | 
    
         
            +
            #  rb.add(section) #  table have a #report_building method
         
     | 
| 
      
 23 
     | 
    
         
            +
            #  rb.add("Another text") #  used directly
         
     | 
| 
      
 24 
     | 
    
         
            +
            #  rb.name="Text output"
         
     | 
| 
      
 25 
     | 
    
         
            +
            #  puts rb.to_text
         
     | 
| 
      
 26 
     | 
    
         
            +
            #  rb.name="Html output"
         
     | 
| 
      
 27 
     | 
    
         
            +
            #  puts rb.to_html
         
     | 
| 
      
 28 
     | 
    
         
            +
            # 
         
     | 
| 
      
 29 
     | 
    
         
            +
            # * Using a block, you can control directly the generator
         
     | 
| 
      
 30 
     | 
    
         
            +
            # 
         
     | 
| 
      
 31 
     | 
    
         
            +
            #  require "reportbuilder"    
         
     | 
| 
      
 32 
     | 
    
         
            +
            #  rb=ReportBuilder.new do
         
     | 
| 
      
 33 
     | 
    
         
            +
            #   text("2")
         
     | 
| 
      
 34 
     | 
    
         
            +
            #   section(:name=>"Section 1") do
         
     | 
| 
      
 35 
     | 
    
         
            +
            #    table(:name=>"Table", :header=>%w{id name}) do
         
     | 
| 
      
 36 
     | 
    
         
            +
            #     row([1,"John"])
         
     | 
| 
      
 37 
     | 
    
         
            +
            #     hr
         
     | 
| 
      
 38 
     | 
    
         
            +
            #     row([2,"Peter"])
         
     | 
| 
      
 39 
     | 
    
         
            +
            #    end
         
     | 
| 
      
 40 
     | 
    
         
            +
            #   end
         
     | 
| 
      
 41 
     | 
    
         
            +
            #   preformatted("Another Text")
         
     | 
| 
      
 42 
     | 
    
         
            +
            #  end
         
     | 
| 
      
 43 
     | 
    
         
            +
            #  rb.name="Text output"
         
     | 
| 
      
 44 
     | 
    
         
            +
            #  puts rb.to_text
         
     | 
| 
      
 45 
     | 
    
         
            +
            #  rb.name="Html output"
         
     | 
| 
      
 46 
     | 
    
         
            +
            #  puts rb.to_html
         
     | 
| 
       6 
47 
     | 
    
         
             
            class ReportBuilder
         
     | 
| 
       7 
48 
     | 
    
         
             
              attr_reader :elements
         
     | 
| 
       8 
     | 
    
         
            -
               
     | 
| 
       9 
     | 
    
         
            -
               
     | 
| 
       10 
     | 
    
         
            -
               
     | 
| 
      
 49 
     | 
    
         
            +
              # Name of report
         
     | 
| 
      
 50 
     | 
    
         
            +
              attr_accessor :name
         
     | 
| 
      
 51 
     | 
    
         
            +
              # Doesn't print a title if set to true
         
     | 
| 
      
 52 
     | 
    
         
            +
              attr_accessor :no_title
         
     | 
| 
      
 53 
     | 
    
         
            +
              
         
     | 
| 
      
 54 
     | 
    
         
            +
              VERSION = '1.0.0'
         
     | 
| 
      
 55 
     | 
    
         
            +
              # Generates and optionally save the report on one function
         
     | 
| 
      
 56 
     | 
    
         
            +
              def self.generate(options=Hash.new, &block)
         
     | 
| 
      
 57 
     | 
    
         
            +
                options[:filename]||=nil
         
     | 
| 
      
 58 
     | 
    
         
            +
                options[:format]||="text"
         
     | 
| 
      
 59 
     | 
    
         
            +
                
         
     | 
| 
      
 60 
     | 
    
         
            +
                if options[:filename] and options[:filename]=~/\.(\w+?)$/
         
     | 
| 
      
 61 
     | 
    
         
            +
                  options[:format]=$1
         
     | 
| 
      
 62 
     | 
    
         
            +
                  options[:format]="text" if options[:format]=="txt"
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
                file=options.delete(:filename)
         
     | 
| 
      
 65 
     | 
    
         
            +
                format=options.delete(:format).to_s
         
     | 
| 
      
 66 
     | 
    
         
            +
                format[0]=format[0,1].upcase
         
     | 
| 
      
 67 
     | 
    
         
            +
                
         
     | 
| 
      
 68 
     | 
    
         
            +
                
         
     | 
| 
      
 69 
     | 
    
         
            +
                rb=ReportBuilder.new(options)
         
     | 
| 
      
 70 
     | 
    
         
            +
                rb.add(block)
         
     | 
| 
      
 71 
     | 
    
         
            +
                generator=Generator.const_get(format.to_sym).new(rb, options)
         
     | 
| 
      
 72 
     | 
    
         
            +
                generator.parse
         
     | 
| 
      
 73 
     | 
    
         
            +
                out=generator.out
         
     | 
| 
      
 74 
     | 
    
         
            +
                unless file.nil?
         
     | 
| 
      
 75 
     | 
    
         
            +
                  File.open(file,"wb") do |fp|
         
     | 
| 
      
 76 
     | 
    
         
            +
                    fp.write out
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
                else
         
     | 
| 
      
 79 
     | 
    
         
            +
                  out
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
              end
         
     | 
| 
       11 
82 
     | 
    
         
             
              # Create a new Report
         
     | 
| 
       12 
     | 
    
         
            -
              def initialize( 
     | 
| 
       13 
     | 
    
         
            -
                name||="Report "+Time.new.to_s
         
     | 
| 
       14 
     | 
    
         
            -
                 
     | 
| 
       15 
     | 
    
         
            -
                @ 
     | 
| 
       16 
     | 
    
         
            -
                @ 
     | 
| 
      
 83 
     | 
    
         
            +
              def initialize(options=Hash.new,&block)
         
     | 
| 
      
 84 
     | 
    
         
            +
                options[:name]||="Report "+Time.new.to_s
         
     | 
| 
      
 85 
     | 
    
         
            +
                @no_title=options.delete :no_title
         
     | 
| 
      
 86 
     | 
    
         
            +
                @name=options.delete :name 
         
     | 
| 
      
 87 
     | 
    
         
            +
                @options=options
         
     | 
| 
       17 
88 
     | 
    
         
             
                @elements=Array.new
         
     | 
| 
      
 89 
     | 
    
         
            +
                add(block) if block
         
     | 
| 
       18 
90 
     | 
    
         
             
              end
         
     | 
| 
       19 
91 
     | 
    
         
             
              # Add an element to the report.
         
     | 
| 
       20 
92 
     | 
    
         
             
              # If parameters is an object which respond to :to_reportbuilder,
         
     | 
| 
       21 
93 
     | 
    
         
             
              # this method will called.
         
     | 
| 
       22 
94 
     | 
    
         
             
              # Otherwise, the element itself will be added
         
     | 
| 
       23 
95 
     | 
    
         
             
              def add(element)
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
              end
         
     | 
| 
       26 
     | 
    
         
            -
              # Returns a Section
         
     | 
| 
       27 
     | 
    
         
            -
              def section(options={})
         
     | 
| 
       28 
     | 
    
         
            -
                Section.new(options)
         
     | 
| 
       29 
     | 
    
         
            -
              end
         
     | 
| 
       30 
     | 
    
         
            -
              def image(filename)
         
     | 
| 
       31 
     | 
    
         
            -
                Image.new(filename)
         
     | 
| 
       32 
     | 
    
         
            -
              end
         
     | 
| 
       33 
     | 
    
         
            -
              # Returns a Table
         
     | 
| 
       34 
     | 
    
         
            -
              def table(h=[])
         
     | 
| 
       35 
     | 
    
         
            -
                  Table.new(h)
         
     | 
| 
      
 96 
     | 
    
         
            +
                @elements.push(element)
         
     | 
| 
       36 
97 
     | 
    
         
             
              end
         
     | 
| 
       37 
98 
     | 
    
         
             
              # Returns an Html output
         
     | 
| 
       38 
     | 
    
         
            -
              def to_html( 
     | 
| 
       39 
     | 
    
         
            -
                gen = Generator::Html.new(self 
     | 
| 
      
 99 
     | 
    
         
            +
              def to_html()
         
     | 
| 
      
 100 
     | 
    
         
            +
                gen = Generator::Html.new(self,@options)
         
     | 
| 
       40 
101 
     | 
    
         
             
                gen.parse
         
     | 
| 
       41 
102 
     | 
    
         
             
                gen.out
         
     | 
| 
       42 
103 
     | 
    
         
             
              end
         
     | 
| 
       43 
     | 
    
         
            -
               
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
      
 104 
     | 
    
         
            +
              # Save an html file
         
     | 
| 
      
 105 
     | 
    
         
            +
              def save_html(file)
         
     | 
| 
      
 106 
     | 
    
         
            +
                options=@options.dup
         
     | 
| 
      
 107 
     | 
    
         
            +
                options[:directory]=File.dirname(file)
         
     | 
| 
      
 108 
     | 
    
         
            +
                gen=Generator::Html.new(self, options)
         
     | 
| 
       45 
109 
     | 
    
         
             
                gen.parse
         
     | 
| 
       46 
     | 
    
         
            -
                 
     | 
| 
       47 
     | 
    
         
            -
                  fp.write(gen.out)
         
     | 
| 
       48 
     | 
    
         
            -
                }
         
     | 
| 
      
 110 
     | 
    
         
            +
                gen.save(file)
         
     | 
| 
       49 
111 
     | 
    
         
             
              end
         
     | 
| 
       50 
112 
     | 
    
         
             
              # Returns a Text output
         
     | 
| 
       51 
     | 
    
         
            -
              def to_text( 
     | 
| 
       52 
     | 
    
         
            -
                gen=Generator::Text.new(self, options)
         
     | 
| 
       53 
     | 
    
         
            -
                gen.parse
         
     | 
| 
      
 113 
     | 
    
         
            +
              def to_text()
         
     | 
| 
      
 114 
     | 
    
         
            +
                gen=Generator::Text.new(self, @options)
         
     | 
| 
      
 115 
     | 
    
         
            +
                gen.parse 
         
     | 
| 
       54 
116 
     | 
    
         
             
                gen.out
         
     | 
| 
       55 
117 
     | 
    
         
             
              end
         
     | 
| 
       56 
118 
     | 
    
         
             
              alias_method :to_s, :to_text
         
     | 
| 
         @@ -1,11 +1,12 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            class ReportBuilder
         
     | 
| 
       2 
2 
     | 
    
         
             
              # Abstract class for generators.
         
     | 
| 
       3 
     | 
    
         
            -
              # 
     | 
| 
       4 
     | 
    
         
            -
              # On parse_cycle()....
         
     | 
| 
      
 3 
     | 
    
         
            +
              # A generator is a class which control the output for a ReportBuilder object
         
     | 
| 
       5 
4 
     | 
    
         
             
              #
         
     | 
| 
       6 
5 
     | 
    
         
             
              class Generator
         
     | 
| 
      
 6 
     | 
    
         
            +
                # Level of heading. See ReportBuilder::Section for using it.
         
     | 
| 
       7 
7 
     | 
    
         
             
                attr_reader :parse_level
         
     | 
| 
       8 
     | 
    
         
            -
                #  
     | 
| 
      
 8 
     | 
    
         
            +
                # Options for Generator. Passed by ReportBuilder class on creation
         
     | 
| 
      
 9 
     | 
    
         
            +
                attr_reader :options
         
     | 
| 
       9 
10 
     | 
    
         
             
                def initialize(builder, options)
         
     | 
| 
       10 
11 
     | 
    
         
             
                  @builder=builder
         
     | 
| 
       11 
12 
     | 
    
         
             
                  @parse_level=0
         
     | 
| 
         @@ -16,53 +17,91 @@ class ReportBuilder 
     | 
|
| 
       16 
17 
     | 
    
         
             
                  @list_tables=[]
         
     | 
| 
       17 
18 
     | 
    
         | 
| 
       18 
19 
     | 
    
         
             
                end
         
     | 
| 
       19 
     | 
    
         
            -
                 
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
      
 20 
     | 
    
         
            +
                # Parse the output. Could be reimplemented on subclasses
         
     | 
| 
      
 21 
     | 
    
         
            +
                def parse
         
     | 
| 
      
 22 
     | 
    
         
            +
                  parse_cycle(@builder)
         
     | 
| 
       21 
23 
     | 
    
         
             
                end
         
     | 
| 
       22 
     | 
    
         
            -
                #  
     | 
| 
      
 24 
     | 
    
         
            +
                # Save the output of generator to a file
         
     | 
| 
      
 25 
     | 
    
         
            +
                def save(filename)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  File.open(filename, "wb") do |fp|
         
     | 
| 
      
 27 
     | 
    
         
            +
                    fp.write(out)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
                
         
     | 
| 
      
 31 
     | 
    
         
            +
                def default_options # :nodoc:
         
     | 
| 
      
 32 
     | 
    
         
            +
                  Hash.new
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
                
         
     | 
| 
      
 35 
     | 
    
         
            +
                # Parse each element of the container
         
     | 
| 
       23 
36 
     | 
    
         
             
                def parse_cycle(container)
         
     | 
| 
       24 
37 
     | 
    
         
             
                  @parse_level+=1
         
     | 
| 
       25 
38 
     | 
    
         
             
                  container.elements.each do |element|
         
     | 
| 
       26 
39 
     | 
    
         
             
                    parse_element(element)
         
     | 
| 
       27 
40 
     | 
    
         
             
                  end
         
     | 
| 
       28 
41 
     | 
    
         
             
                  @parse_level-=1
         
     | 
| 
       29 
     | 
    
         
            -
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
                end    
         
     | 
| 
       30 
43 
     | 
    
         | 
| 
      
 44 
     | 
    
         
            +
                # Parse one object, using this workflow
         
     | 
| 
      
 45 
     | 
    
         
            +
                # * If is a block, evaluate it
         
     | 
| 
      
 46 
     | 
    
         
            +
                # * Use #report_building_FORMAT
         
     | 
| 
      
 47 
     | 
    
         
            +
                # * Use #report_building
         
     | 
| 
      
 48 
     | 
    
         
            +
                # * Use #to_s
         
     | 
| 
       31 
49 
     | 
    
         
             
                def parse_element(element)
         
     | 
| 
       32 
     | 
    
         
            -
                  method=(" 
     | 
| 
       33 
     | 
    
         
            -
                  if element. 
     | 
| 
      
 50 
     | 
    
         
            +
                  method=("report_building_" + self.class::PREFIX).intern
         
     | 
| 
      
 51 
     | 
    
         
            +
                  if element.is_a? Proc
         
     | 
| 
      
 52 
     | 
    
         
            +
                    element.arity==0 ? instance_eval(&element) : element.call(self)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  elsif element.respond_to? method
         
     | 
| 
       34 
54 
     | 
    
         
             
                    element.send(method, self)
         
     | 
| 
       35 
     | 
    
         
            -
                  elsif element.respond_to? : 
     | 
| 
       36 
     | 
    
         
            -
                    element.send(: 
     | 
| 
      
 55 
     | 
    
         
            +
                  elsif element.respond_to? :report_building
         
     | 
| 
      
 56 
     | 
    
         
            +
                    element.send(:report_building, self)
         
     | 
| 
       37 
57 
     | 
    
         
             
                  else
         
     | 
| 
       38 
     | 
    
         
            -
                     
     | 
| 
      
 58 
     | 
    
         
            +
                    text(element.to_s)
         
     | 
| 
       39 
59 
     | 
    
         
             
                  end
         
     | 
| 
       40 
60 
     | 
    
         
             
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
                # Create and parse a table. Use a block to control the table
         
     | 
| 
      
 62 
     | 
    
         
            +
                def table(opt=Hash.new, &block)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  parse_element(ReportBuilder::Table.new(opt,&block))
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
                # Create and parse an image.
         
     | 
| 
      
 66 
     | 
    
         
            +
                def image(filename,opt=Hash.new)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  parse_element(ReportBuilder::Image.new(filename,opt))
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
                # Create and parse an image. Use a block to insert element inside the block
         
     | 
| 
      
 70 
     | 
    
         
            +
                def section(opt=Hash.new, &block)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  parse_element(ReportBuilder::Section.new(opt,&block))
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
       41 
73 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
                 
     | 
| 
      
 74 
     | 
    
         
            +
                # Add a paragraph to the report
         
     | 
| 
      
 75 
     | 
    
         
            +
                def text(t)
         
     | 
| 
       43 
76 
     | 
    
         
             
                  raise "Implement this"
         
     | 
| 
       44 
77 
     | 
    
         
             
                end
         
     | 
| 
       45 
     | 
    
         
            -
                 
     | 
| 
      
 78 
     | 
    
         
            +
                # Add html code. Only parsed with generator which understand html 
         
     | 
| 
      
 79 
     | 
    
         
            +
                def html(t)
         
     | 
| 
       46 
80 
     | 
    
         
             
                  raise "Implement this"
         
     | 
| 
       47 
81 
     | 
    
         
             
                end
         
     | 
| 
       48 
     | 
    
         
            -
                 
     | 
| 
      
 82 
     | 
    
         
            +
                # Add preformatted text
         
     | 
| 
      
 83 
     | 
    
         
            +
                def preformatted(t)
         
     | 
| 
       49 
84 
     | 
    
         
             
                  raise "Implement this"
         
     | 
| 
       50 
85 
     | 
    
         
             
                end
         
     | 
| 
       51 
     | 
    
         
            -
                 
     | 
| 
      
 86 
     | 
    
         
            +
                # Add a TOC (Table of Contents) entry
         
     | 
| 
      
 87 
     | 
    
         
            +
                # Return the name of anchor
         
     | 
| 
      
 88 
     | 
    
         
            +
                def toc_entry(name)
         
     | 
| 
       52 
89 
     | 
    
         
             
                  anchor="toc_#{@entry_n}"
         
     | 
| 
       53 
90 
     | 
    
         
             
                  @entry_n+=1
         
     | 
| 
       54 
91 
     | 
    
         
             
                  @toc.push([anchor, name, parse_level])
         
     | 
| 
       55 
92 
     | 
    
         
             
                  anchor
         
     | 
| 
       56 
93 
     | 
    
         
             
                end
         
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                # Add an entry for  table index.
         
     | 
| 
       58 
96 
     | 
    
         
             
                # Returns the name of the anchor
         
     | 
| 
       59 
     | 
    
         
            -
                def  
     | 
| 
      
 97 
     | 
    
         
            +
                def table_entry(name)
         
     | 
| 
       60 
98 
     | 
    
         
             
                  anchor="table_#{@table_n}"
         
     | 
| 
       61 
99 
     | 
    
         
             
                  @table_n+=1
         
     | 
| 
       62 
100 
     | 
    
         
             
                  @list_tables.push([anchor,name])
         
     | 
| 
       63 
101 
     | 
    
         
             
                  anchor
         
     | 
| 
       64 
102 
     | 
    
         
             
                end
         
     | 
| 
       65 
103 
     | 
    
         
             
              end
         
     | 
| 
      
 104 
     | 
    
         
            +
              
         
     | 
| 
       66 
105 
     | 
    
         
             
              class ElementGenerator
         
     | 
| 
       67 
106 
     | 
    
         
             
                def initialize(generator,element)
         
     | 
| 
       68 
107 
     | 
    
         
             
                  @element=element
         
     | 
| 
         @@ -1,40 +1,39 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'fileutils'
         
     | 
| 
       2 
2 
     | 
    
         
             
            class ReportBuilder
         
     | 
| 
       3 
3 
     | 
    
         
             
              class Generator
         
     | 
| 
       4 
     | 
    
         
            -
                
         
     | 
| 
       5 
4 
     | 
    
         
             
                class Html < Generator
         
     | 
| 
       6 
5 
     | 
    
         
             
                  PREFIX="html"
         
     | 
| 
       7 
6 
     | 
    
         
             
                  attr_reader :toc
         
     | 
| 
      
 7 
     | 
    
         
            +
                  attr_reader :directory
         
     | 
| 
       8 
8 
     | 
    
         
             
                  def initialize(builder, options)
         
     | 
| 
       9 
9 
     | 
    
         
             
                    super
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @directory = @options.delete :directory
         
     | 
| 
       10 
11 
     | 
    
         
             
                    @body=""
         
     | 
| 
       11 
12 
     | 
    
         
             
                    @headers=[]
         
     | 
| 
       12 
13 
     | 
    
         
             
                    @footers=[]
         
     | 
| 
       13 
14 
     | 
    
         
             
                  end
         
     | 
| 
       14 
     | 
    
         
            -
                  def  
     | 
| 
       15 
     | 
    
         
            -
                     
     | 
| 
       16 
     | 
    
         
            -
                    # add_js(File.dirname(__FILE__)+"/../../../data/reportbuilder.js")
         
     | 
| 
       17 
     | 
    
         
            -
                    parse_cycle(@builder)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  def default_options
         
     | 
| 
      
 16 
     | 
    
         
            +
                    {:directory => Dir.pwd}
         
     | 
| 
       18 
17 
     | 
    
         
             
                  end
         
     | 
| 
       19 
18 
     | 
    
         
             
                  def basic_css
         
     | 
| 
       20 
     | 
    
         
            -
            <<-HERE
         
     | 
| 
       21 
     | 
    
         
            -
            <style>
         
     | 
| 
       22 
     | 
    
         
            -
            body {
         
     | 
| 
       23 
     | 
    
         
            -
            margin:0;
         
     | 
| 
       24 
     | 
    
         
            -
            padding:1em;
         
     | 
| 
       25 
     | 
    
         
            -
            }
         
     | 
| 
       26 
     | 
    
         
            -
            table {
         
     | 
| 
       27 
     | 
    
         
            -
            border-collapse: collapse;
         
     | 
| 
      
 19 
     | 
    
         
            +
                    <<-HERE
         
     | 
| 
      
 20 
     | 
    
         
            +
                    <style>
         
     | 
| 
      
 21 
     | 
    
         
            +
                    body {
         
     | 
| 
      
 22 
     | 
    
         
            +
                      margin:0;
         
     | 
| 
      
 23 
     | 
    
         
            +
                      padding:1em;
         
     | 
| 
      
 24 
     | 
    
         
            +
                    }
         
     | 
| 
      
 25 
     | 
    
         
            +
                    table {
         
     | 
| 
      
 26 
     | 
    
         
            +
                      border-collapse: collapse;
         
     | 
| 
       28 
27 
     | 
    
         | 
| 
       29 
     | 
    
         
            -
            }
         
     | 
| 
       30 
     | 
    
         
            -
            table td {
         
     | 
| 
       31 
     | 
    
         
            -
            border: 1px solid black;
         
     | 
| 
       32 
     | 
    
         
            -
            }
         
     | 
| 
       33 
     | 
    
         
            -
            .section {
         
     | 
| 
       34 
     | 
    
         
            -
            margin:0.5em;
         
     | 
| 
       35 
     | 
    
         
            -
            }
         
     | 
| 
       36 
     | 
    
         
            -
            </style>
         
     | 
| 
       37 
     | 
    
         
            -
            HERE
         
     | 
| 
      
 28 
     | 
    
         
            +
                    }
         
     | 
| 
      
 29 
     | 
    
         
            +
                    table td {
         
     | 
| 
      
 30 
     | 
    
         
            +
                      border: 1px solid black;
         
     | 
| 
      
 31 
     | 
    
         
            +
                    }
         
     | 
| 
      
 32 
     | 
    
         
            +
                    .section {
         
     | 
| 
      
 33 
     | 
    
         
            +
                      margin:0.5em;
         
     | 
| 
      
 34 
     | 
    
         
            +
                    }
         
     | 
| 
      
 35 
     | 
    
         
            +
                    </style>
         
     | 
| 
      
 36 
     | 
    
         
            +
                    HERE
         
     | 
| 
       38 
37 
     | 
    
         
             
                  end
         
     | 
| 
       39 
38 
     | 
    
         
             
                  def out
         
     | 
| 
       40 
39 
     | 
    
         
             
                    out= <<-HERE
         
     | 
| 
         @@ -44,14 +43,16 @@ HERE 
     | 
|
| 
       44 
43 
     | 
    
         
             
            <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
         
     | 
| 
       45 
44 
     | 
    
         
             
            <title>#{@builder.name}</title>
         
     | 
| 
       46 
45 
     | 
    
         
             
            #{basic_css}
         
     | 
| 
       47 
     | 
    
         
            -
            HERE
         
     | 
| 
      
 46 
     | 
    
         
            +
                    HERE
         
     | 
| 
       48 
47 
     | 
    
         
             
                    out << @headers.join("\n")
         
     | 
| 
       49 
48 
     | 
    
         
             
                    out << "</head><body>\n"
         
     | 
| 
       50 
49 
     | 
    
         
             
                    out << "<h1>#{@builder.name}</h1>"
         
     | 
| 
       51 
     | 
    
         
            -
                    if(@toc.size>0)
         
     | 
| 
       52 
     | 
    
         
            -
                    out << "<div  
     | 
| 
      
 50 
     | 
    
         
            +
                    if(@toc.size>0)                      
         
     | 
| 
      
 51 
     | 
    
         
            +
                    out << "<div id='toc'><div class='title'>List of contents</div>\n"
         
     | 
| 
       53 
52 
     | 
    
         
             
                      actual_level=0
         
     | 
| 
      
 53 
     | 
    
         
            +
                      
         
     | 
| 
       54 
54 
     | 
    
         
             
                      @toc.each do |anchor,name,level|
         
     | 
| 
      
 55 
     | 
    
         
            +
                        
         
     | 
| 
       55 
56 
     | 
    
         
             
                        if actual_level!=level
         
     | 
| 
       56 
57 
     | 
    
         
             
                          if actual_level > level
         
     | 
| 
       57 
58 
     | 
    
         
             
                            (actual_level-level).times { out << "</ul>\n"}
         
     | 
| 
         @@ -59,71 +60,61 @@ HERE 
     | 
|
| 
       59 
60 
     | 
    
         
             
                            (level-actual_level).times { out << "<ul>\n"}
         
     | 
| 
       60 
61 
     | 
    
         
             
                          end
         
     | 
| 
       61 
62 
     | 
    
         
             
                        end
         
     | 
| 
      
 63 
     | 
    
         
            +
                        
         
     | 
| 
       62 
64 
     | 
    
         
             
                        out << "<li><a href='##{anchor}'>#{name}</a></li>\n"
         
     | 
| 
       63 
65 
     | 
    
         
             
                        actual_level=level
         
     | 
| 
       64 
66 
     | 
    
         
             
                      end
         
     | 
| 
       65 
67 
     | 
    
         
             
                      actual_level.times { out << "</ul>\n"}
         
     | 
| 
       66 
68 
     | 
    
         
             
                      out << "</div>\n"
         
     | 
| 
       67 
69 
     | 
    
         
             
                    end
         
     | 
| 
       68 
     | 
    
         
            -
                    if (@list_tables.size>0) 
     | 
| 
      
 70 
     | 
    
         
            +
                    if (@list_tables.size>0)
         
     | 
| 
       69 
71 
     | 
    
         
             
                      out << "<div class='tot'><div class='title'>List of tables</div><ul>"
         
     | 
| 
       70 
72 
     | 
    
         
             
                      @list_tables.each {|anchor,name|
         
     | 
| 
       71 
73 
     | 
    
         
             
                        out << "<li><a href='#"+anchor+"'>#{name}</a></li>"
         
     | 
| 
       72 
74 
     | 
    
         
             
                      }
         
     | 
| 
       73 
75 
     | 
    
         
             
                      out << "</ul></div>\n"
         
     | 
| 
       74 
76 
     | 
    
         
             
                    end
         
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
       76 
78 
     | 
    
         
             
                    out << @body
         
     | 
| 
       77 
79 
     | 
    
         
             
                    out << @footers.join("\n")
         
     | 
| 
       78 
80 
     | 
    
         
             
                    out << "</body></html>"
         
     | 
| 
      
 81 
     | 
    
         
            +
                    out
         
     | 
| 
       79 
82 
     | 
    
         
             
                  end
         
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
                  
         
     | 
| 
       82 
     | 
    
         
            -
                  def add_image(filename)
         
     | 
| 
       83 
     | 
    
         
            -
                    if(File.exists? filename)
         
     | 
| 
       84 
     | 
    
         
            -
                      if(!File.exists? @builder.dir+"/images/"+File.basename(filename))
         
     | 
| 
       85 
     | 
    
         
            -
                        FileUtils.mkdir @builder.dir+"/images"
         
     | 
| 
       86 
     | 
    
         
            -
                        FileUtils.cp filename, @builder.dir+"/images/"+File.basename(filename)
         
     | 
| 
       87 
     | 
    
         
            -
                      end
         
     | 
| 
       88 
     | 
    
         
            -
                    end
         
     | 
| 
       89 
     | 
    
         
            -
                    "images/"+File.basename(filename)
         
     | 
| 
       90 
     | 
    
         
            -
                  end
         
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
                  def add_js(js)
         
     | 
| 
      
 83 
     | 
    
         
            +
                  def js(js)
         
     | 
| 
       93 
84 
     | 
    
         
             
                    if(File.exists? js)
         
     | 
| 
       94 
     | 
    
         
            -
                      if(!File.exists? @ 
     | 
| 
       95 
     | 
    
         
            -
                        FileUtils.mkdir @ 
     | 
| 
       96 
     | 
    
         
            -
                        FileUtils.cp js,@ 
     | 
| 
      
 85 
     | 
    
         
            +
                      if(!File.exists? @directory+"/js/"+File.basename(js))
         
     | 
| 
      
 86 
     | 
    
         
            +
                        FileUtils.mkdir @directory+"/js"
         
     | 
| 
      
 87 
     | 
    
         
            +
                        FileUtils.cp js,@directory+"/js/"+File.basename(js)
         
     | 
| 
       97 
88 
     | 
    
         
             
                      end
         
     | 
| 
       98 
89 
     | 
    
         
             
                      @headers.push("<script type='text/javascript' src='js/#{File.basename(js)}'></script>")
         
     | 
| 
       99 
90 
     | 
    
         
             
                    end
         
     | 
| 
       100 
91 
     | 
    
         
             
                  end
         
     | 
| 
       101 
     | 
    
         
            -
             
     | 
| 
       102 
     | 
    
         
            -
                  def  
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                  def css(css)
         
     | 
| 
       103 
94 
     | 
    
         
             
                    if(File.exists? css)
         
     | 
| 
       104 
     | 
    
         
            -
                      if(!File.exists? @ 
     | 
| 
       105 
     | 
    
         
            -
                        FileUtils.mkdir @ 
     | 
| 
       106 
     | 
    
         
            -
                        FileUtils.cp css 
     | 
| 
      
 95 
     | 
    
         
            +
                      if(!File.exists? @directory+"/css/"+File.basename(css))
         
     | 
| 
      
 96 
     | 
    
         
            +
                        FileUtils.mkdir @directory+"/css"
         
     | 
| 
      
 97 
     | 
    
         
            +
                        FileUtils.cp css, @directory+"/css/"+File.basename(css)
         
     | 
| 
       107 
98 
     | 
    
         
             
                      end
         
     | 
| 
       108 
99 
     | 
    
         
             
                      @headers.push("<link rel='stylesheet' type='text/css' href='css/#{File.basename(css)}' />")
         
     | 
| 
       109 
100 
     | 
    
         
             
                    end
         
     | 
| 
       110 
101 
     | 
    
         
             
                  end
         
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
                  def  
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                  def text(t)
         
     | 
| 
       114 
105 
     | 
    
         
             
                    ws=(" "*parse_level*2)
         
     | 
| 
       115 
106 
     | 
    
         
             
                    @body << ws << "<p>#{t}</p>\n"
         
     | 
| 
       116 
107 
     | 
    
         
             
                  end
         
     | 
| 
       117 
     | 
    
         
            -
                  def  
     | 
| 
      
 108 
     | 
    
         
            +
                  def html(t)
         
     | 
| 
       118 
109 
     | 
    
         
             
                    ws=(" "*parse_level*2)
         
     | 
| 
       119 
110 
     | 
    
         
             
                    @body << ws << t << "\n"
         
     | 
| 
       120 
111 
     | 
    
         
             
                  end
         
     | 
| 
       121 
     | 
    
         
            -
                  def  
     | 
| 
      
 112 
     | 
    
         
            +
                  def preformatted(t)
         
     | 
| 
       122 
113 
     | 
    
         
             
                    ws=(" "*parse_level*2)
         
     | 
| 
       123 
114 
     | 
    
         
             
                    @body << ws << "<pre>#{t}</pre>\n"
         
     | 
| 
       124 
     | 
    
         
            -
             
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
       125 
116 
     | 
    
         
             
                  end
         
     | 
| 
       126 
     | 
    
         
            -
             
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
       127 
118 
     | 
    
         
             
                end
         
     | 
| 
       128 
119 
     | 
    
         
             
              end
         
     | 
| 
       129 
120 
     | 
    
         
             
            end
         
     |