wayneeseguin-dynamic_reports 0.0.2

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.
@@ -0,0 +1,38 @@
1
+ require File.dirname(__FILE__) + '/base'
2
+ module GoogleChart
3
+
4
+ # Generates a Scatter chart.
5
+ #
6
+ # ==== Example
7
+ # sc = GoogleChart::ScatterChart.new('320x200',"Scatter Chart")
8
+ # sc.data "Scatter Set", [[1,1,], [2,2], [3,3], [4,4]]
9
+ # sc.point_sizes [10,15,30,55]
10
+ # puts sc.to_url
11
+ class ScatterChart < Base
12
+
13
+ # Initializes the Scatter Chart with a +chart_size+ (in WIDTHxHEIGHT format) and a +chart_title+
14
+ def initialize(chart_size='300x200', chart_title=nil) # :yield: self
15
+ super(chart_size, chart_title)
16
+ self.chart_type = :s
17
+ self.show_legend = false
18
+ @point_sizes = []
19
+ yield self if block_given?
20
+ end
21
+
22
+ def process_data
23
+ # Interleave X and Y co-ordinate data
24
+ encoded_data = join_encoded_data([encode_data(x_data[0],max_x_value), encode_data(y_data[0],max_y_value)])
25
+ # Add point sizes data if it exists
26
+ unless @point_sizes.empty?
27
+ encoded_data = join_encoded_data([encoded_data, encode_data(@point_sizes)])
28
+ end
29
+ return encoded_data
30
+ end
31
+
32
+ # Specify the data point sizes of the Scatter chart (optional). The data point sizes are scaled with this data set.
33
+ def point_sizes(values)
34
+ @point_sizes = values
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,36 @@
1
+ require File.dirname(__FILE__) + '/base'
2
+ module GoogleChart
3
+ # Generates a Venn Diagram.
4
+ #
5
+ # Supply three vd.data statements of label, size, color for circles A, B, C. Then, intersections with four values:
6
+ # * the first value specifies the area of A intersecting B
7
+ # * the second value specifies the area of B intersecting C
8
+ # * the third value specifies the area of C intersecting A
9
+ # * the fourth value specifies the area of A intersecting B intersecting C
10
+ #
11
+ # vd = GoogleChart::VennDiagram.new("320x200", 'Venn Diagram')
12
+ # vd.data "Blue", 100, '0000ff'
13
+ # vd.data "Green", 80, '00ff00'
14
+ # vd.data "Red", 60, 'ff0000'
15
+ # vd.intersections 30,30,30,10
16
+ # puts vd.to_url
17
+ class VennDiagram < Base
18
+
19
+ # Initializes the Venn Diagram with a +chart_size+ (in WIDTHxHEIGHT format) and a +chart_title+
20
+ def initialize(chart_size='300x200', chart_title=nil) # :yield: self
21
+ super(chart_size, chart_title)
22
+ self.chart_type = :v
23
+ @intersections = []
24
+ yield self if block_given?
25
+ end
26
+
27
+ def process_data
28
+ encode_data(@data + @intersections)
29
+ end
30
+
31
+ # Specify the intersections of the circles in the Venn Diagram. See the Rdoc for class for sample
32
+ def intersections(*values)
33
+ @intersections = values
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,11 @@
1
+ %w(
2
+ base
3
+ pie_chart
4
+ line_chart
5
+ bar_chart
6
+ venn_diagram
7
+ scatter_chart
8
+ financial_line_chart
9
+ ).each do |filename|
10
+ require File.dirname(__FILE__) + "/google_chart/#{filename}"
11
+ end
@@ -0,0 +1 @@
1
+ <%= yield %>
@@ -0,0 +1,73 @@
1
+ <% if report.class_name.nil? %>
2
+ <style type="text/css">
3
+ .dynamic_report .report_title {
4
+ font-size:16pt;
5
+ font-weight:bold;
6
+ margin:10px 0px;
7
+ }
8
+ .dynamic_report .report_sub_title {
9
+ font-size:14pt;
10
+ color:black;
11
+ margin:10px 0px;
12
+ }
13
+ .dynamic_report table tr th {
14
+ color: white;
15
+ background: gray;
16
+ padding:5px;
17
+ }
18
+ .dynamic_report table tr td {
19
+ border: 1px solid black;
20
+ padding:3px 15px;
21
+ }
22
+ .dynamic_report .report_charts {
23
+ width:100%;
24
+ }
25
+
26
+ .dynamic_report .report_chart {
27
+ margin:15px;
28
+ }
29
+ </style>
30
+ <% end %>
31
+
32
+ <div id="<%= report.class_name %>" class="dynamic_report">
33
+ <%= "<div class='report_title'>#{report.title}</div>" if report.title %>
34
+ <%= "<div class='report_sub_title'>#{report.sub_title}</div>" if report.sub_title %>
35
+ <table class="report" border="0" cellpadding="0" cellspacing="0">
36
+ <thead class="report_header">
37
+ <tr class="report_header_row">
38
+ <% report.columns.each do |column| %>
39
+ <th>
40
+ <%= options[:titleize] ? titleize(column) : column %>
41
+ </th>
42
+ <% end %>
43
+ </tr>
44
+ </thead>
45
+ <tbody class="report_body">
46
+ <% report.records.each do |record| %>
47
+ <tr class="report_row">
48
+ <% report.columns.each do |column| %>
49
+ <td>
50
+ <% if record.is_a?(Hash) %>
51
+ <%= (options[:commas] == true) ? commify(record[column]) : record[column] %>
52
+ <% elsif record.respond_to?(column.to_sym) %>
53
+ <%= (options[:commas] == true) ? commify(record.send(column.to_sym)) : record.send(column.to_sym) %>
54
+ <% else %>
55
+ <%= column %>
56
+ <% end %>
57
+ </td>
58
+ <% end %>
59
+ </tr>
60
+ <% end %>
61
+ </tbody>
62
+ </table>
63
+
64
+ <div class="report_charts">
65
+ <% report.charts.to_a.each do |chart| %>
66
+ <span class="report_chart">
67
+ <%= "<img src='#{chart_url(chart,report)}' alt='#{chart.name}'>" %>
68
+ </span>
69
+ <% end %>
70
+ </div>
71
+
72
+ </div>
73
+
@@ -0,0 +1,62 @@
1
+ - if report.class_name.nil?
2
+ %style{type => "text/css"}
3
+ \.dynamic_report .report_title {
4
+ font-size:16pt;
5
+ font-weight:bold;
6
+ margin:10px 0px;
7
+ }
8
+ \.dynamic_report .report_sub_title {
9
+ font-size:14pt;
10
+ color:black;
11
+ margin:10px 0px;
12
+ }
13
+ \.dynamic_report table tr th {
14
+ color: white;
15
+ background: gray;
16
+ padding:5px;
17
+ }
18
+ \.dynamic_report table tr td {
19
+ border: 1px solid black;
20
+ padding:3px 15px;
21
+ }
22
+ \.dynamic_report .report_charts {
23
+ width:100%;
24
+ }
25
+ \.dynamic_report .report_chart {
26
+ margin:15px;
27
+ }
28
+
29
+ .dynamic_report{ :id => report.class_name }
30
+ - if report.title
31
+ %h2.report_title
32
+ = report.title
33
+
34
+ - if report.sub_title
35
+ %h3.report_sub_title
36
+ = report.sub_title
37
+
38
+ %table.report{ :cellspacing => "0", :border => "0", :cellpadding => "0" }
39
+ %thead.report_header
40
+ %tr.report_header_row
41
+ - report.columns.each do |column|
42
+ %th
43
+ = options[:titleize] ? titleize(column) : column
44
+ %tbody.report_body
45
+ - report.records.each do |record|
46
+ %tr.report_row
47
+ - report.columns.each do |column|
48
+ %td
49
+ - if record.is_a?(Hash)
50
+ = (options[:commas] == true) ? commify(record[column]) : record[column]
51
+ - elsif record.respond_to?(column.to_sym)
52
+ = (options[:commas] == true) ? commify(record.send(column.to_sym)) : record.send(column.to_sym)
53
+ - else
54
+ = column
55
+
56
+ - if report.charts && report.charts.class === Hash
57
+ - report.charts.each_pair do |name, chart|
58
+ .chart
59
+ %h2
60
+ = name
61
+ %img{:src => chart_url(chart), :alt => name}
62
+
@@ -0,0 +1,30 @@
1
+ module DynamicReports
2
+ class View
3
+
4
+ include Templates
5
+
6
+ attr_accessor :template, :views, :report
7
+ @@cached_templates = {}
8
+ @template = {}
9
+ @views = {}
10
+
11
+ def options
12
+ @options ||= {}
13
+ end
14
+
15
+ def initialize(report)
16
+ @template = report.template
17
+ @report = report
18
+ @views = report.views
19
+ end
20
+
21
+ class << self
22
+ def cached_templates
23
+ @@cached_templates
24
+ end
25
+ end
26
+
27
+ # TODO: Investigate if we can remove the need for caller_locations here?
28
+ def self.caller_locations ; [] ; end
29
+ end
30
+ end
@@ -0,0 +1,47 @@
1
+ # :include: README
2
+
3
+ # Library Files
4
+ module DynamicReports
5
+ @@default_view_paths = ["#{File::dirname(File::expand_path(__FILE__))}/dynamic_reports/views/"]
6
+ def self.default_view_paths
7
+ @@default_view_paths
8
+ end
9
+ def self.default_view_paths=(paths)
10
+ @@default_view_paths = paths
11
+ end
12
+ end
13
+
14
+ require "dynamic_reports/charts"
15
+ require "dynamic_reports/reports"
16
+ require "dynamic_reports/templates"
17
+ require "dynamic_reports/views"
18
+ require "dynamic_reports/vendor/google_chart"
19
+
20
+
21
+ # TODO: Figure out why this will not load:
22
+ # require "dynamic_reports/rails"
23
+ # For now placing the code right here:
24
+ if defined?(Rails)
25
+ # Load all defined reports.
26
+ # Question: How to get Rails to reload files other than ones matching the requested constant...
27
+ #Dir.glob("#{File.join(Rails.root, "app", "reports")}/*.rb").each { |file| require file }
28
+ ActiveSupport::Dependencies.load_paths << File.join(Rails.root, "app", "reports")
29
+ # Question: Should we allow for report directory nesting ?
30
+
31
+ # Set default views directory
32
+ # TODO: These should be added to Rails views directories?
33
+ DynamicReports.default_view_paths += [
34
+ File.join(Rails.root, "app", "views", "reports"),
35
+ File.join(Rails.root, "app", "views", "layouts")
36
+ ]
37
+
38
+ # TODO: Render extension
39
+
40
+ # TODO: AR extensions:
41
+ # has_report :daily, :columns => [...], :options => {...}, :title => ...
42
+ # Which will generate a report object DailyReport with the given definition.
43
+ # Everything after the name corresponds to options available in the configuration block.
44
+
45
+ # TODO: Generator
46
+ end
47
+
@@ -0,0 +1,61 @@
1
+ class ChartsTest < Test::Unit::TestCase
2
+ context "charts" do
3
+ setup do
4
+ class TheReport < DynamicReports::Report
5
+ chart :the_chart_name, :an => "option", :another => "option" do
6
+ title "awesome report!"
7
+ type :svg
8
+ height "350"
9
+ width "250"
10
+ columns :pageviews
11
+ label_column "created_at"
12
+ end
13
+ chart :the_other_chart_name do
14
+ title "Some other chart"
15
+ end
16
+ end
17
+ end
18
+
19
+ should "allow specification of options to the chart beyond it's attributes." do
20
+ hash = {
21
+ :name => :the_chart_name,
22
+ :an => "option",
23
+ :type => :svg,
24
+ :another => "option",
25
+ :title=>"awesome report!",
26
+ :height=>"350",
27
+ :width=>"250",
28
+ :columns=>[:pageviews],
29
+ :label_column => "created_at"
30
+ }
31
+ assert_equal hash, TheReport.chart_with_name(:the_chart_name).options
32
+ end
33
+
34
+ should "allow setting their name" do
35
+ assert_equal :the_chart_name, TheReport.chart_with_name(:the_chart_name).name
36
+ end
37
+
38
+ should "allow setting their title" do
39
+ assert_equal "awesome report!", TheReport.chart_with_name(:the_chart_name).title
40
+ end
41
+
42
+ should "allow setting their type" do
43
+ assert_equal :svg, TheReport.chart_with_name(:the_chart_name).type
44
+ end
45
+
46
+ should "allow setting their width" do
47
+ assert_equal "250" ,TheReport.chart_with_name(:the_chart_name).width
48
+ end
49
+
50
+ should "allow setting their height" do
51
+ assert_equal "350", TheReport.chart_with_name(:the_chart_name).height
52
+ end
53
+
54
+ should "allow definition of multiple charts" do
55
+ #require "ruby-debug" ; debugger
56
+ assert_contains TheReport.charts[0].name, :the_chart_name
57
+ assert_contains TheReport.charts[1].name, :the_other_chart_name
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,77 @@
1
+ class ReportsTest < Test::Unit::TestCase
2
+ context "a report" do
3
+
4
+ setup do
5
+ class TheReport < DynamicReports::Report
6
+ name "The Report!"
7
+ title "Daily Report"
8
+ sub_title "Happens every day, ya!"
9
+ columns :recorded_at, :viewed_on, :pageviews_count, :visits_count, :conversions_count
10
+
11
+ chart :visits do
12
+ title "testing chart"
13
+ columns :visits
14
+ type "line"
15
+ end
16
+ end
17
+ @array_records = DynamicReports::Test::ArrayRecords.generate(TheReport, :count => 10)
18
+ @object_records = DynamicReports::Test::ObjectRecords.generate(TheReport, :count => 10)
19
+ end
20
+
21
+ should "allow setting the title of a report" do
22
+ assert_equal "Daily Report", TheReport.title
23
+ end
24
+
25
+ should "allow setting the sub title of a report" do
26
+ assert_equal "Happens every day, ya!", TheReport.sub_title
27
+ end
28
+
29
+ should "allow setting the columns to report on" do
30
+ assert_equal [:recorded_at, :viewed_on, :pageviews_count, :visits_count, :conversions_count], TheReport.columns
31
+ end
32
+
33
+ should "return an instantiated report .on is called" do
34
+ assert_kind_of DynamicReports::Report,
35
+ TheReport.on(@array_records)
36
+ end
37
+
38
+ should "An instantiated report should return html table report when to_html is called" do
39
+ assert_match(/<table class="report"/, TheReport.on(@array_records).to_html)
40
+ end
41
+
42
+ should "An instantiated report should contain the rendered chart that was defined" do
43
+ assert_match(/class="report_charts"/, TheReport.on(@array_records).to_html)
44
+ end
45
+
46
+ context "Report with templates and views specified" do
47
+ setup do
48
+ class SpecificTemplateReport < DynamicReports::Report
49
+ name "A report with specified template!"
50
+ title "Specify Template Report"
51
+ sub_title "template is 'other_template'"
52
+ columns :recorded_at, :viewed_on, :pageviews_count, :visits_count, :conversions_count
53
+ template :specific_template
54
+ views "#{File::dirname(File::expand_path(__FILE__))}/views/"
55
+ end
56
+ @array_records = DynamicReports::Test::ArrayRecords.generate(SpecificTemplateReport, :count => 10)
57
+ @object_records = DynamicReports::Test::ObjectRecords.generate(SpecificTemplateReport, :count => 10)
58
+ end
59
+
60
+ should "allow setting of the views directories" do
61
+ assert_contains SpecificTemplateReport.views,
62
+ "#{File::dirname(File::expand_path(__FILE__))}/views/"
63
+ end
64
+
65
+ should "the instance should have the same views as the class" do
66
+ assert_contains SpecificTemplateReport.on(@array_records).views,
67
+ "#{File::dirname(File::expand_path(__FILE__))}/views/"
68
+ end
69
+
70
+ should "render with the specified template, from the specified views directory" do
71
+ assert_equal "This is the specified template!",
72
+ SpecificTemplateReport.on(@array_records).to_html.strip
73
+ end
74
+ end
75
+ end
76
+
77
+ end
@@ -0,0 +1,3 @@
1
+ class TemplatesTest < Test::Unit::TestCase
2
+
3
+ end
@@ -0,0 +1,5 @@
1
+ class ReportsTest < Test::Unit::TestCase
2
+ context "View" do
3
+
4
+ end
5
+ end
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ require "rubygems"
3
+ require "test/unit/testsuite"
4
+ require "test/unit/ui/console/testrunner"
5
+ #require "test/unit/color"
6
+ require "shoulda"
7
+ require "zentest"
8
+
9
+ # Libraries
10
+ require "dynamic_reports"
11
+ require "test/test_helper"
12
+
13
+ # Test files.
14
+ require "test/dynamic_reports/charts_test"
15
+ require "test/dynamic_reports/reports_test"
16
+ require "test/dynamic_reports/views_test"
17
+
18
+ require "test/unit"
File without changes
@@ -0,0 +1,64 @@
1
+ require "ostruct"
2
+
3
+ module DynamicReports
4
+ module Test
5
+
6
+ class ArrayRecords
7
+ def self.generate(report, *options)
8
+ records = []
9
+ options = options.shift || {}
10
+ (0..(options[:count].to_i)).each do |index|
11
+ hash = {}
12
+ report.columns.each do |column|
13
+ hash[column.to_s] =
14
+ case column.to_s
15
+ when /_at$/
16
+ (DateTime.now-100)+index
17
+ when /_on$/
18
+ (Date.today-100)+index
19
+ when /_id$/,/_count$/
20
+ rand(10000)
21
+ else
22
+ column
23
+ end
24
+ end
25
+ records << hash
26
+ end
27
+ records
28
+ end
29
+ end
30
+
31
+ class ObjectRecords
32
+ def self.generate(report,*options)
33
+ records = []
34
+ options = options.shift || {}
35
+ (0..(options[:count].to_i)).each do |index|
36
+ object = OpenStruct.new(report.columns)
37
+ report.columns.each do |column|
38
+ value = case column.to_s
39
+ when /_at$/
40
+ (DateTime.now-100)+index
41
+ when /_on$/
42
+ (Date.today-100)+index
43
+ when /_id$/,/_count$/
44
+ rand(10000)
45
+ else
46
+ column
47
+ end
48
+
49
+ object.send(column.to_sym, value)
50
+
51
+ records << object
52
+ end
53
+ records
54
+ end
55
+ end
56
+ end
57
+
58
+ class ARRecords
59
+ def self.generate(*options)
60
+ end
61
+ end
62
+ end
63
+
64
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wayneeseguin-dynamic_reports
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Wayne E. Seguin
8
+ - Joshua Lippiner
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-07-01 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: Dynamic Ruby Reporting Engine with support for Charts.
18
+ email: wayneeseguin@gmail.com, jlippiner@gmail.com
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files:
24
+ - README
25
+ - README.rdoc
26
+ files:
27
+ - HISTORY
28
+ - README
29
+ - dynamic_reports.gemspec
30
+ - lib/dynamic_reports.rb
31
+ - lib/dynamic_reports/charts.rb
32
+ - lib/dynamic_reports/reports.rb
33
+ - lib/dynamic_reports/templates.rb
34
+ - lib/dynamic_reports/vendor/google_chart.rb
35
+ - lib/dynamic_reports/vendor/google_chart/bar_chart.rb
36
+ - lib/dynamic_reports/vendor/google_chart/base.rb
37
+ - lib/dynamic_reports/vendor/google_chart/financial_line_chart.rb
38
+ - lib/dynamic_reports/vendor/google_chart/line_chart.rb
39
+ - lib/dynamic_reports/vendor/google_chart/pie_chart.rb
40
+ - lib/dynamic_reports/vendor/google_chart/scatter_chart.rb
41
+ - lib/dynamic_reports/vendor/google_chart/venn_diagram.rb
42
+ - lib/dynamic_reports/views.rb
43
+ - lib/dynamic_reports/views/default_layout.html.erb
44
+ - lib/dynamic_reports/views/default_report.html.erb
45
+ - lib/dynamic_reports/views/default_report.html.haml
46
+ - README.rdoc
47
+ has_rdoc: false
48
+ homepage: http://dynamicreports.rubyforge.org/
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --inline-source
52
+ - --charset=UTF-8
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ requirements: []
68
+
69
+ rubyforge_project: dynamicreports
70
+ rubygems_version: 1.2.0
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: Dynamic Ruby Reporting Engine with support for Charts
74
+ test_files:
75
+ - test/dynamic_reports/charts_test.rb
76
+ - test/dynamic_reports/reports_test.rb
77
+ - test/dynamic_reports/templates_test.rb
78
+ - test/dynamic_reports/views_test.rb
79
+ - test/dynamic_reports.rb
80
+ - test/factories/records.rb
81
+ - test/test_helper.rb