dynamic_reports 0.0.1 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +8 -1
- data/README +81 -23
- data/README.rdoc +247 -0
- data/dynamic_reports.gemspec +62 -0
- data/lib/dynamic_reports.rb +8 -2
- data/lib/dynamic_reports/reports.rb +66 -14
- data/lib/dynamic_reports/templates.rb +50 -7
- data/lib/dynamic_reports/views/default_report.html.erb +22 -53
- data/lib/dynamic_reports/views/default_report.html.haml +8 -36
- data/test/dynamic_reports.rb +18 -0
- data/test/dynamic_reports/charts_test.rb +61 -0
- data/test/dynamic_reports/reports_test.rb +77 -0
- data/test/dynamic_reports/templates_test.rb +3 -0
- data/test/dynamic_reports/views_test.rb +5 -0
- data/test/factories/records.rb +0 -0
- data/test/test_helper.rb +64 -0
- metadata +28 -18
- data/gemspec.rb +0 -24
data/HISTORY
CHANGED
data/README
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
= Dynamic Reports
|
2
2
|
|
3
3
|
A dynamic reporting engine for Ruby / Rails
|
4
|
-
|
4
|
+
|
5
5
|
== Reports
|
6
6
|
|
7
7
|
The dynamic reports gem was created to fill a HUGE hole that we felt existed in the
|
@@ -114,32 +114,90 @@
|
|
114
114
|
label_column "created_at"
|
115
115
|
end
|
116
116
|
|
117
|
-
==
|
118
|
-
|
119
|
-
The reports are, by default, stylized with an inline style sheet. The styles produce a nicely formatted grid with
|
120
|
-
a white on black header row and black on white columns with a gray border througout.
|
117
|
+
== External Links
|
121
118
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
119
|
+
Dynamic Reports supports linking from any column within your table. To add a link to a column, add the following
|
120
|
+
to a report definition:
|
121
|
+
|
122
|
+
link :column, url
|
123
|
+
|
124
|
+
For example:
|
125
|
+
|
126
|
+
class OrdersReport < DynamicReports::Report
|
127
|
+
title "Orders Report"
|
128
|
+
subtitle "All orders recorded in database"
|
129
|
+
columns :total, :created_at
|
130
|
+
|
131
|
+
link :total, '/report/daily_sales'
|
132
|
+
end
|
133
|
+
|
134
|
+
You can also pass parameters to the URL based on values from the underlying model. To pass a parameter, surround the
|
135
|
+
field name with {}. The parameter does NOT need to be a displayed, column. For example, you might want to pass
|
136
|
+
an external link an ID column but not display this column on the table.
|
137
|
+
|
138
|
+
For example:
|
139
|
+
|
140
|
+
class OrdersReport < DynamicReports::Report
|
141
|
+
title "Orders Report"
|
142
|
+
subtitle "All orders recorded in database"
|
143
|
+
columns :total, :created_at
|
144
|
+
|
145
|
+
link :total, '/report/item_sales?id={id}' # => Will substitute ID for the value of ID associated with that record
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
== Subreports
|
128
150
|
|
129
|
-
|
130
|
-
|
151
|
+
Dynamic Reports supports the display of a sub-report within any report. This is accomplished using the jQuery library
|
152
|
+
available at http://www.jquery.com.
|
153
|
+
|
154
|
+
Sub-reports are created using the same definition format that you would use to create a standard report. The only
|
155
|
+
difference is that it is displayed INLINE when an associated link is clicked.
|
156
|
+
|
157
|
+
A sub-report is defined using the same format as a LINK above, but is labeled as:
|
158
|
+
|
159
|
+
subreport :column, url
|
160
|
+
|
161
|
+
For example, if you wanted to show all sales and allow a user to click on a specific item to see all historic sales
|
162
|
+
inline for just that item, you would do the following:
|
163
|
+
|
164
|
+
IN CONTROLLER:
|
165
|
+
|
166
|
+
def orders
|
167
|
+
@orders = Order.find(:all, :limit => 25)
|
168
|
+
render :text => OrdersReport.on(@orders).to_html, :layout => "application"
|
169
|
+
end
|
170
|
+
|
171
|
+
def item_sales
|
172
|
+
@item_orders = Order.find_by_id(params[:id])
|
173
|
+
render :text => ItemSales.on(@orders).to_html, :layout => "application"
|
174
|
+
end
|
175
|
+
|
176
|
+
REPORT DEFINITIONS
|
177
|
+
|
178
|
+
class OrdersReport < DynamicReports::Report
|
179
|
+
title "Orders Report"
|
180
|
+
subtitle "All orders recorded in database"
|
181
|
+
columns :total, :created_at
|
182
|
+
|
183
|
+
subreport :total, '/report/item_sales?id={id}' # => Will substitute ID for the value of ID associated with that record
|
184
|
+
end
|
185
|
+
|
186
|
+
class ItemSales < DynamicReports::Report
|
187
|
+
columns :item, :price, :created_at
|
188
|
+
end
|
189
|
+
|
190
|
+
Subreports can also be nested.
|
191
|
+
|
192
|
+
== Rails Usage
|
131
193
|
|
132
|
-
|
133
|
-
|
194
|
+
The gem includes a stylesheet and javascript based on jQuery. To add both to your Rails project,
|
195
|
+
simply type "drsetup" from the project root. This will add:
|
134
196
|
|
135
|
-
|
136
|
-
|
137
|
-
.my_class_name table tr th {}
|
138
|
-
.my_class_name table tr td {}
|
139
|
-
.my_class_name .report_charts {} // all charts are displayed within this div
|
140
|
-
.my_class_name .report_chart {} // represents an individual chart
|
197
|
+
public/stylesheets/dynamic_reports.css (controls style of dynamic reports)
|
198
|
+
public/javascripts/dynamic_reports.js (controls display of subreports)
|
141
199
|
|
142
|
-
|
200
|
+
You can then modify these files as you see fit.
|
143
201
|
|
144
202
|
Inside the initializer block in config/environment.rb
|
145
203
|
|
@@ -179,7 +237,7 @@
|
|
179
237
|
== Thanks To
|
180
238
|
|
181
239
|
* Daniel Neighman
|
182
|
-
* Kenneth Kalmer
|
240
|
+
* Kenneth Kalmer & Nic Young
|
183
241
|
* Yehuda Katz
|
184
242
|
|
185
243
|
For their encouragement, feedback and advise.
|
data/README.rdoc
ADDED
@@ -0,0 +1,247 @@
|
|
1
|
+
= Dynamic Reports
|
2
|
+
|
3
|
+
A dynamic reporting engine for Ruby / Rails
|
4
|
+
|
5
|
+
== Reports
|
6
|
+
|
7
|
+
The dynamic reports gem was created to fill a HUGE hole that we felt existed in the
|
8
|
+
Ruby community - the ability to QUICKLY create stylized admin reports and charts for
|
9
|
+
people to use to view key metrics and data.
|
10
|
+
|
11
|
+
Sample uses include the ability to quickly display sales data if your an eShop, our
|
12
|
+
site metrics if you are recording your own site visits, or user feedback if you are storing
|
13
|
+
feedback in a model somewhere.
|
14
|
+
|
15
|
+
Basically, with DR you can create a stylized table of ANY information found in a model
|
16
|
+
(kind of like looking at the grid output from a GUI query analyzer) as well as add Google
|
17
|
+
Charts API powered line, pie, bar or column charts of any numeric data. All this can
|
18
|
+
be done by simply creating a report definition and feeding it your data.
|
19
|
+
|
20
|
+
While this library is usable in any Ruby application it was made mainly with Rails in mind.
|
21
|
+
Suppose we have an online store and we wish to add reporting to the admin area quickly and easily.
|
22
|
+
First we define a report in app/reports/orders_report.rb, something like:
|
23
|
+
|
24
|
+
class OrdersReport < DynamicReports::Report
|
25
|
+
title "Orders Report"
|
26
|
+
subtitle "All orders recorded in database"
|
27
|
+
columns :total, :created_at
|
28
|
+
end
|
29
|
+
|
30
|
+
Then in our admin/reports controller (this can be any controller) we define an action to deliver the report:
|
31
|
+
|
32
|
+
def orders
|
33
|
+
@orders = Order.find(:all, :limit => 25)
|
34
|
+
render :text => OrdersReport.on(@orders).to_html, :layout => "application"
|
35
|
+
end
|
36
|
+
|
37
|
+
This will render an html table containing some basic styling and containing the columns 'total' and 'created_at' from the order objects.
|
38
|
+
Note that the report Title will be "Orders Report" and it's name will be :orders_report
|
39
|
+
Report#on expects that it receives an object that responds to #each and
|
40
|
+
That each object that it iterates over is either a
|
41
|
+
* An object
|
42
|
+
* A Hash
|
43
|
+
that responds to a method / has keys for each column defined within the report.
|
44
|
+
|
45
|
+
|
46
|
+
Templating engines may also be specified, currently :erb and :haml are supported (we will soon be adding :csv and :pdf) like so:
|
47
|
+
|
48
|
+
render :text => OrdersReport.on(@orders).to_html(:engine => :haml), :layout => "application"
|
49
|
+
|
50
|
+
Note that erb is the default templating engine since it is available by default in Ruby.
|
51
|
+
|
52
|
+
Now let us extend our report definition to specify a template to use!
|
53
|
+
|
54
|
+
class OrdersReport < DynamicReports::Report
|
55
|
+
title "Orders Report"
|
56
|
+
subtitle "All orders recorded in database"
|
57
|
+
columns :total, :created_at
|
58
|
+
|
59
|
+
template :my_custom_template
|
60
|
+
end
|
61
|
+
|
62
|
+
This will look in app/views/reports/ for a template named "my_custom_template.html.erb" by default.
|
63
|
+
If you specify :engine => :haml then it will look for "my_custom_template.html.haml"
|
64
|
+
|
65
|
+
If you happen to have your report templates in a different location you can specify this as follows:
|
66
|
+
|
67
|
+
class OrdersReport < DynamicReports::Report
|
68
|
+
title "Orders Report"
|
69
|
+
subtitle "All orders recorded in database"
|
70
|
+
columns :total, :created_at
|
71
|
+
|
72
|
+
template :my_custom_template
|
73
|
+
views "app/views/admin/reports/"
|
74
|
+
end
|
75
|
+
|
76
|
+
And DynamicReports will look for the specified template in app/views/reports as well as app/views/admin/reports.
|
77
|
+
|
78
|
+
It is also worth pointing out that you can have as many dynamic reports in a view as you wish, simply include
|
79
|
+
each report render where desired within the view.
|
80
|
+
|
81
|
+
== Charts
|
82
|
+
|
83
|
+
Charts can be defined on a report easily. Let's say we wish to chart the total versus the item quantity sold for our Orders Report exmaple:
|
84
|
+
|
85
|
+
class OrdersReport < DynamicReports::Report
|
86
|
+
title "Orders Report"
|
87
|
+
subtitle "All orders recorded in database"
|
88
|
+
columns :total, :created_at
|
89
|
+
|
90
|
+
chart :total_vs_quantity do
|
91
|
+
columns :total, :quantity
|
92
|
+
label_column "created_at"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
This will render a *line* chart by default displaying the columns total and quantity.
|
97
|
+
Chart types may be specified easily:
|
98
|
+
|
99
|
+
type :bar
|
100
|
+
|
101
|
+
Available chart types are:
|
102
|
+
|
103
|
+
* :line (default)
|
104
|
+
* :bar
|
105
|
+
* :pie
|
106
|
+
|
107
|
+
Since DynamicReport's charts utilize the Google Chart API, you can easily extend each chart by passing a hash of chart options as part
|
108
|
+
of the block. The options are appended onto the request to the API so they should follow the Google's API commands (http://code.google.com/apis/chart/)
|
109
|
+
|
110
|
+
For example, to add min, max and average labels to the example chart, you would do something like this:
|
111
|
+
|
112
|
+
chart :total_vs_quantity, {:chxt => "r", :chxl => "0:|min|average|max"} do
|
113
|
+
columns :total, :quantity
|
114
|
+
label_column "created_at"
|
115
|
+
end
|
116
|
+
|
117
|
+
== External Links
|
118
|
+
|
119
|
+
Dynamic Reports supports linking from any column within your table. To add a link to a column, add the following
|
120
|
+
to a report definition:
|
121
|
+
|
122
|
+
link :column, url
|
123
|
+
|
124
|
+
For example:
|
125
|
+
|
126
|
+
class OrdersReport < DynamicReports::Report
|
127
|
+
title "Orders Report"
|
128
|
+
subtitle "All orders recorded in database"
|
129
|
+
columns :total, :created_at
|
130
|
+
|
131
|
+
link :total, '/report/daily_sales'
|
132
|
+
end
|
133
|
+
|
134
|
+
You can also pass parameters to the URL based on values from the underlying model. To pass a parameter, surround the
|
135
|
+
field name with {}. The parameter does NOT need to be a displayed, column. For example, you might want to pass
|
136
|
+
an external link an ID column but not display this column on the table.
|
137
|
+
|
138
|
+
For example:
|
139
|
+
|
140
|
+
class OrdersReport < DynamicReports::Report
|
141
|
+
title "Orders Report"
|
142
|
+
subtitle "All orders recorded in database"
|
143
|
+
columns :total, :created_at
|
144
|
+
|
145
|
+
link :total, '/report/item_sales?id={id}' # => Will substitute ID for the value of ID associated with that record
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
== Subreports
|
150
|
+
|
151
|
+
Dynamic Reports supports the display of a sub-report within any report. This is accomplished using the jQuery library
|
152
|
+
available at http://www.jquery.com.
|
153
|
+
|
154
|
+
Sub-reports are created using the same definition format that you would use to create a standard report. The only
|
155
|
+
difference is that it is displayed INLINE when an associated link is clicked.
|
156
|
+
|
157
|
+
A sub-report is defined using the same format as a LINK above, but is labeled as:
|
158
|
+
|
159
|
+
subreport :column, url
|
160
|
+
|
161
|
+
For example, if you wanted to show all sales and allow a user to click on a specific item to see all historic sales
|
162
|
+
inline for just that item, you would do the following:
|
163
|
+
|
164
|
+
IN CONTROLLER:
|
165
|
+
|
166
|
+
def orders
|
167
|
+
@orders = Order.find(:all, :limit => 25)
|
168
|
+
render :text => OrdersReport.on(@orders).to_html, :layout => "application"
|
169
|
+
end
|
170
|
+
|
171
|
+
def item_sales
|
172
|
+
@item_orders = Order.find_by_id(params[:id])
|
173
|
+
render :text => ItemSales.on(@orders).to_html, :layout => "application"
|
174
|
+
end
|
175
|
+
|
176
|
+
REPORT DEFINITIONS
|
177
|
+
|
178
|
+
class OrdersReport < DynamicReports::Report
|
179
|
+
title "Orders Report"
|
180
|
+
subtitle "All orders recorded in database"
|
181
|
+
columns :total, :created_at
|
182
|
+
|
183
|
+
subreport :total, '/report/item_sales?id={id}' # => Will substitute ID for the value of ID associated with that record
|
184
|
+
end
|
185
|
+
|
186
|
+
class ItemSales < DynamicReports::Report
|
187
|
+
columns :item, :price, :created_at
|
188
|
+
end
|
189
|
+
|
190
|
+
Subreports can also be nested.
|
191
|
+
|
192
|
+
== Rails Usage
|
193
|
+
|
194
|
+
The gem includes a stylesheet and javascript based on jQuery. To add both to your Rails project,
|
195
|
+
simply type "drsetup" from the project root. This will add:
|
196
|
+
|
197
|
+
public/stylesheets/dynamic_reports.css (controls style of dynamic reports)
|
198
|
+
public/javascripts/dynamic_reports.js (controls display of subreports)
|
199
|
+
|
200
|
+
You can then modify these files as you see fit.
|
201
|
+
|
202
|
+
Inside the initializer block in config/environment.rb
|
203
|
+
|
204
|
+
config.gem "dynamic_reports"
|
205
|
+
|
206
|
+
Then define your reports (as exampled above) in app/reports/*_report.rb
|
207
|
+
If you would like to customize the default report simply create your report templates
|
208
|
+
within app/views/reports/*_report.<content-type>.<engine>.
|
209
|
+
|
210
|
+
Two Rails features that we are currently working on are:
|
211
|
+
|
212
|
+
* generator
|
213
|
+
* render extensions
|
214
|
+
|
215
|
+
== Optional Dependencies
|
216
|
+
|
217
|
+
We are currently examining solutions for csv, pdf and charting.
|
218
|
+
|
219
|
+
* Fastercsv # csv
|
220
|
+
* Prawn # pdf
|
221
|
+
* flying saucer # html => PDF - if jRuby available
|
222
|
+
* amcharts # Charting, note that default is built in google charts.
|
223
|
+
|
224
|
+
These will be defined/implemented using DynamicReports plugin API (not implemented yet)
|
225
|
+
Which allows for user defined plugins of arbitrary types beyond html,csv,pdf,xml
|
226
|
+
|
227
|
+
== Contact / Feedback
|
228
|
+
|
229
|
+
If you have any suggestions on improvement please send us an email.
|
230
|
+
|
231
|
+
== Authors (alphabetically)
|
232
|
+
|
233
|
+
Joshua Lippiner (jlippiner@gmail.com)
|
234
|
+
|
235
|
+
Wayne E. Seguin (wayneeseguin@gmail.com, irc: wayneeseguin)
|
236
|
+
|
237
|
+
== Thanks To
|
238
|
+
|
239
|
+
* Daniel Neighman
|
240
|
+
* Kenneth Kalmer & Nic Young
|
241
|
+
* Yehuda Katz
|
242
|
+
|
243
|
+
For their encouragement, feedback and advise.
|
244
|
+
|
245
|
+
== Source
|
246
|
+
http://github.com/wayneeseguin/dynamic_reports
|
247
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{dynamic_reports}
|
5
|
+
s.version = "0.0.4"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Wayne E. Seguin", "Joshua Lippiner"]
|
9
|
+
s.date = %q{2009-07-01}
|
10
|
+
s.description = %q{Dynamic Ruby Reporting Engine with support for Charts.}
|
11
|
+
s.email = %q{wayneeseguin@gmail.com, jlippiner@gmail.com}
|
12
|
+
s.extra_rdoc_files = [
|
13
|
+
"README",
|
14
|
+
"README.rdoc"
|
15
|
+
]
|
16
|
+
s.files = [
|
17
|
+
"HISTORY",
|
18
|
+
"README",
|
19
|
+
"dynamic_reports.gemspec",
|
20
|
+
"lib/dynamic_reports.rb",
|
21
|
+
"lib/dynamic_reports/charts.rb",
|
22
|
+
"lib/dynamic_reports/reports.rb",
|
23
|
+
"lib/dynamic_reports/templates.rb",
|
24
|
+
"lib/dynamic_reports/vendor/google_chart.rb",
|
25
|
+
"lib/dynamic_reports/vendor/google_chart/bar_chart.rb",
|
26
|
+
"lib/dynamic_reports/vendor/google_chart/base.rb",
|
27
|
+
"lib/dynamic_reports/vendor/google_chart/financial_line_chart.rb",
|
28
|
+
"lib/dynamic_reports/vendor/google_chart/line_chart.rb",
|
29
|
+
"lib/dynamic_reports/vendor/google_chart/pie_chart.rb",
|
30
|
+
"lib/dynamic_reports/vendor/google_chart/scatter_chart.rb",
|
31
|
+
"lib/dynamic_reports/vendor/google_chart/venn_diagram.rb",
|
32
|
+
"lib/dynamic_reports/views.rb",
|
33
|
+
"lib/dynamic_reports/views/default_layout.html.erb",
|
34
|
+
"lib/dynamic_reports/views/default_report.html.erb",
|
35
|
+
"lib/dynamic_reports/views/default_report.html.haml"
|
36
|
+
]
|
37
|
+
s.homepage = %q{http://dynamicreports.rubyforge.org/}
|
38
|
+
s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
|
39
|
+
s.require_paths = ["lib"]
|
40
|
+
s.rubyforge_project = %q{dynamicreports}
|
41
|
+
s.rubygems_version = %q{1.3.3}
|
42
|
+
s.summary = %q{Dynamic Ruby Reporting Engine with support for Charts}
|
43
|
+
s.test_files = [
|
44
|
+
"test/dynamic_reports/charts_test.rb",
|
45
|
+
"test/dynamic_reports/reports_test.rb",
|
46
|
+
"test/dynamic_reports/templates_test.rb",
|
47
|
+
"test/dynamic_reports/views_test.rb",
|
48
|
+
"test/dynamic_reports.rb",
|
49
|
+
"test/factories/records.rb",
|
50
|
+
"test/test_helper.rb"
|
51
|
+
]
|
52
|
+
|
53
|
+
if s.respond_to? :specification_version then
|
54
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
55
|
+
s.specification_version = 3
|
56
|
+
|
57
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
58
|
+
else
|
59
|
+
end
|
60
|
+
else
|
61
|
+
end
|
62
|
+
end
|
data/lib/dynamic_reports.rb
CHANGED
@@ -22,7 +22,14 @@ require "dynamic_reports/vendor/google_chart"
|
|
22
22
|
# require "dynamic_reports/rails"
|
23
23
|
# For now placing the code right here:
|
24
24
|
if defined?(Rails)
|
25
|
-
#
|
25
|
+
# ath_to_lib = File.join(Rails.root, "app") #adjust if necessary
|
26
|
+
# path_to_tree = "#{path_to_lib}/reports"
|
27
|
+
# Dir["#{path_to_tree}/**/*.rb"].each { |fn|
|
28
|
+
# fn =~ /^#{Regexp.escape(path_to_lib)}\/(.*)\.rb$/
|
29
|
+
# require $1
|
30
|
+
# }
|
31
|
+
|
32
|
+
# Load all defined reports.
|
26
33
|
# Question: How to get Rails to reload files other than ones matching the requested constant...
|
27
34
|
#Dir.glob("#{File.join(Rails.root, "app", "reports")}/*.rb").each { |file| require file }
|
28
35
|
ActiveSupport::Dependencies.load_paths << File.join(Rails.root, "app", "reports")
|
@@ -44,4 +51,3 @@ if defined?(Rails)
|
|
44
51
|
|
45
52
|
# TODO: Generator
|
46
53
|
end
|
47
|
-
|
@@ -8,7 +8,7 @@ module DynamicReports
|
|
8
8
|
class Report
|
9
9
|
@@default_engine = "erb"
|
10
10
|
|
11
|
-
attr_accessor :name, :title, :sub_title, :columns, :charts, :records, :template, :class_name, :styles
|
11
|
+
attr_accessor :name, :title, :sub_title, :columns, :charts, :records, :template, :class_name, :styles, :links
|
12
12
|
|
13
13
|
# views accessor, array of view paths.
|
14
14
|
def views
|
@@ -24,7 +24,13 @@ module DynamicReports
|
|
24
24
|
# Views setter and accessor.
|
25
25
|
def views(*array)
|
26
26
|
@views ||= ["#{File::dirname(File::expand_path(__FILE__))}/views/"]
|
27
|
-
array
|
27
|
+
unless array.empty?
|
28
|
+
@views.unshift(array)
|
29
|
+
@views.flatten!
|
30
|
+
@views.uniq!
|
31
|
+
else
|
32
|
+
@views
|
33
|
+
end
|
28
34
|
end
|
29
35
|
|
30
36
|
# class level options accessor
|
@@ -100,7 +106,11 @@ module DynamicReports
|
|
100
106
|
# OrdersReport.template # => :orders
|
101
107
|
#
|
102
108
|
def template(value = nil)
|
103
|
-
|
109
|
+
if value
|
110
|
+
@template = value
|
111
|
+
options[:template] = @template
|
112
|
+
end
|
113
|
+
@template ||= nil
|
104
114
|
end
|
105
115
|
|
106
116
|
# Accessor for columns
|
@@ -160,6 +170,50 @@ module DynamicReports
|
|
160
170
|
chart_options = chart_options.shift || {}
|
161
171
|
charts(Chart.configure(name, chart_options, &block))
|
162
172
|
end
|
173
|
+
|
174
|
+
# Return an array of links defined for the report.
|
175
|
+
def links(object=nil)
|
176
|
+
options[:links] ||= []
|
177
|
+
options[:links] << object if object
|
178
|
+
options[:links]
|
179
|
+
end
|
180
|
+
|
181
|
+
# Define a link for the report
|
182
|
+
#
|
183
|
+
# Pass parameters within {}. Parameters are replaced with the row values
|
184
|
+
# from passed records. You do NOT need to include a parameter value as a
|
185
|
+
# report column for it to be used in a link. For example, you might
|
186
|
+
# want to generate a link with an ID field in it but not display that id
|
187
|
+
# in the actual report. Just include {id} to do this.
|
188
|
+
#
|
189
|
+
# Example:
|
190
|
+
#
|
191
|
+
# link :visits, '/reports/{visit}/details?date={recorded_at}'
|
192
|
+
#
|
193
|
+
def link(column, url, link_options=nil)
|
194
|
+
links({:column => column, :url => url, :link_options => link_options})
|
195
|
+
end
|
196
|
+
|
197
|
+
# Define an inline subreport for the report
|
198
|
+
#
|
199
|
+
# Pass parameters within {}. Parameters are replaced with the row values
|
200
|
+
# from passed records. You do NOT need to include a parameter value as a
|
201
|
+
# report column for it to be used in a link. For example, you might
|
202
|
+
# want to generate a subreport with an ID field in it but not display that id
|
203
|
+
# in the actual report. Just include {id} to do this.
|
204
|
+
#
|
205
|
+
# Example:
|
206
|
+
#
|
207
|
+
# subreport :visits, '/reports/{visit}/details?date={recorded_at}'
|
208
|
+
#
|
209
|
+
# The subreport should be created using the same report definition style
|
210
|
+
# that you use for any other report.
|
211
|
+
#
|
212
|
+
def subreport(column, url, link_options=nil)
|
213
|
+
link_options ||= {}
|
214
|
+
link_options.merge!({:class => 'sub_report_link'})
|
215
|
+
links({:column => column, :url => url, :link_options => link_options})
|
216
|
+
end
|
163
217
|
|
164
218
|
# Method for instanciating a report instance on a set of given records.
|
165
219
|
#
|
@@ -177,14 +231,6 @@ module DynamicReports
|
|
177
231
|
def on(records)
|
178
232
|
new(records, @options)
|
179
233
|
end
|
180
|
-
|
181
|
-
#--
|
182
|
-
# Methods for definining a sub report
|
183
|
-
#def link_column
|
184
|
-
#end
|
185
|
-
#def link_rows
|
186
|
-
#end
|
187
|
-
|
188
234
|
end
|
189
235
|
|
190
236
|
# Instantiate the report on a set of records.
|
@@ -201,10 +247,15 @@ module DynamicReports
|
|
201
247
|
def initialize(records, *new_options)
|
202
248
|
new_options = new_options.shift || {}
|
203
249
|
@records = records
|
204
|
-
|
205
|
-
@views
|
206
|
-
@views
|
250
|
+
|
251
|
+
@views = self.class.views
|
252
|
+
@views.unshift(new_options.delete(:views)) if new_options[:views]
|
253
|
+
@views.flatten!
|
254
|
+
@views.uniq!
|
255
|
+
|
256
|
+
@template = self.class.template
|
207
257
|
@template = new_options.delete(:template) if new_options[:template]
|
258
|
+
|
208
259
|
@options = self.class.options.merge!(new_options)
|
209
260
|
@options.each_pair do |key,value|
|
210
261
|
if key == "chart"
|
@@ -233,6 +284,7 @@ module DynamicReports
|
|
233
284
|
options = (options.shift || {}).merge!(@options || {})
|
234
285
|
# todo: if rails is loaded set the default engine: dynamicreports::report.default_engine
|
235
286
|
engine = options.delete(:engine) || @@default_engine
|
287
|
+
options[:template] = self.class.template
|
236
288
|
view.__send__("#{engine}", options)
|
237
289
|
end
|
238
290
|
|
@@ -32,7 +32,7 @@ module DynamicReports
|
|
32
32
|
|
33
33
|
# TODO: Add Report Helpers for injection
|
34
34
|
def titleize(object)
|
35
|
-
object.to_s.split('_').each{ |word| word.capitalize! }.join(' ')
|
35
|
+
object.to_s.split('_').each{ |word| word.capitalize! }.join(' ')
|
36
36
|
end
|
37
37
|
|
38
38
|
def commify(object)
|
@@ -43,9 +43,44 @@ module DynamicReports
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
+
def linkcheck(record, column_object)
|
47
|
+
val = ''
|
48
|
+
|
49
|
+
if column_object.is_a?(Hash)
|
50
|
+
if column_object.keys.include?(:column)
|
51
|
+
column = column_object[:column]
|
52
|
+
else
|
53
|
+
column = column_object.keys.first # => Josh shortcut :)
|
54
|
+
end
|
55
|
+
else
|
56
|
+
column = column_object
|
57
|
+
end
|
58
|
+
|
59
|
+
report.links.each do |link|
|
60
|
+
if link[:column] == column
|
61
|
+
url = link[:url]
|
62
|
+
url.scan(/\{(\w+)\}/).each do |parameter|
|
63
|
+
parameter = parameter.to_s
|
64
|
+
url = url.gsub("{#{parameter}}", CGI::escape(get_record_value(record, parameter.to_sym).to_s))
|
65
|
+
end
|
66
|
+
|
67
|
+
url_attribute_str = []
|
68
|
+
link[:link_options].keys.each do |key|
|
69
|
+
url_attribute_str << "#{key}='#{link[:link_options][key]}'"
|
70
|
+
end if link[:link_options]
|
71
|
+
|
72
|
+
val = "<a href='#{url}' #{url_attribute_str.join(' ')}>#{get_record_value(record,column)}</a>"
|
73
|
+
break
|
74
|
+
end if link[:column]
|
75
|
+
end if report.links
|
76
|
+
|
77
|
+
val.blank? ? get_record_value(record,column) : val
|
78
|
+
end
|
79
|
+
|
80
|
+
|
46
81
|
def chart_url(chart,report)
|
47
82
|
columns = chart.columns ? chart.columns : report.columns
|
48
|
-
chart_type = chart.type.nil? ? :line : chart.type.to_sym
|
83
|
+
chart_type = chart.type.nil? ? :line : chart.type.to_sym
|
49
84
|
case chart_type
|
50
85
|
when :line
|
51
86
|
Charts.line_chart(chart,columns,report)
|
@@ -62,7 +97,7 @@ module DynamicReports
|
|
62
97
|
end
|
63
98
|
|
64
99
|
private
|
65
|
-
|
100
|
+
|
66
101
|
def render(engine, template, options={}, locals={})
|
67
102
|
# merge app-level options
|
68
103
|
options = self.class.send(engine).merge(options) if self.class.respond_to?(engine)
|
@@ -74,7 +109,7 @@ module DynamicReports
|
|
74
109
|
content_type = options.delete(:content_type)
|
75
110
|
locals = options.delete(:locals) || locals || {}
|
76
111
|
locals.merge!(:report => @report, :options => options || {})
|
77
|
-
|
112
|
+
|
78
113
|
# render template
|
79
114
|
data, options[:filename], options[:line] = lookup_template(engine, template, views, content_type)
|
80
115
|
output = __send__("render_#{engine}", template, data, options, locals)
|
@@ -101,7 +136,7 @@ module DynamicReports
|
|
101
136
|
lookup_template(engine, cached[:template], views, content_type, cached[:filename], cached[:line])
|
102
137
|
else
|
103
138
|
filename = "#{template}.#{content_type}.#{engine}"
|
104
|
-
dir = views.to_a.detect do |view|
|
139
|
+
dir = views.to_a.detect do |view|
|
105
140
|
::File.exists?(::File.join(view, filename))
|
106
141
|
end
|
107
142
|
if dir
|
@@ -172,7 +207,15 @@ module DynamicReports
|
|
172
207
|
require engine.downcase
|
173
208
|
end
|
174
209
|
|
175
|
-
|
176
|
-
|
210
|
+
def get_record_value(record, column)
|
211
|
+
if record.is_a?(Hash)
|
212
|
+
record[column]
|
213
|
+
elsif record.respond_to?(column.to_sym)
|
214
|
+
record.send(column.to_sym)
|
215
|
+
else
|
216
|
+
column
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
177
220
|
end
|
178
221
|
end
|
@@ -1,34 +1,3 @@
|
|
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_subtitle {
|
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
1
|
<div id="<%= report.class_name %>" class="dynamic_report">
|
33
2
|
<%= "<div class='report_title'>#{report.title}</div>" if report.title %>
|
34
3
|
<%= "<div class='report_subtitle'>#{report.sub_title}</div>" if report.sub_title %>
|
@@ -36,38 +5,38 @@
|
|
36
5
|
<thead class="report_header">
|
37
6
|
<tr class="report_header_row">
|
38
7
|
<% report.columns.each do |column| %>
|
39
|
-
|
40
|
-
|
41
|
-
|
8
|
+
<th>
|
9
|
+
<% if column.is_a?(Hash) %>
|
10
|
+
<% if column.keys.include?(:heading) %>
|
11
|
+
<%= options[:titleize] ? titleize(column[:heading]) : column[:heading] %>
|
12
|
+
<% else %>
|
13
|
+
<%= options[:titleize] ? titleize(column.values.first) : column.values.first %>
|
14
|
+
<% end %>
|
15
|
+
<% else %>
|
16
|
+
<%= options[:titleize] ? titleize(column) : column %>
|
17
|
+
<% end %>
|
18
|
+
</th>
|
42
19
|
<% end %>
|
43
20
|
</tr>
|
44
21
|
</thead>
|
45
22
|
<tbody class="report_body">
|
46
23
|
<% report.records.each do |record| %>
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
<% else %>
|
55
|
-
<%= column %>
|
56
|
-
<% end %>
|
57
|
-
</td>
|
58
|
-
<% end %>
|
59
|
-
</tr>
|
24
|
+
<tr class="report_row">
|
25
|
+
<% report.columns.each do |column| %>
|
26
|
+
<td>
|
27
|
+
<%= (options[:commas] == true) ? commify(linkcheck(record,column)) : linkcheck(record,column) %>
|
28
|
+
</td>
|
29
|
+
<% end %>
|
30
|
+
</tr>
|
60
31
|
<% end %>
|
61
32
|
</tbody>
|
62
33
|
</table>
|
63
|
-
|
34
|
+
|
64
35
|
<div class="report_charts">
|
65
36
|
<% report.charts.to_a.each do |chart| %>
|
66
|
-
|
67
|
-
|
68
|
-
|
37
|
+
<span class="report_chart">
|
38
|
+
<%= "<img src='#{chart_url(chart,report)}' alt='#{chart.name}'>" %>
|
39
|
+
</span>
|
69
40
|
<% end %>
|
70
41
|
</div>
|
71
|
-
|
72
42
|
</div>
|
73
|
-
|
@@ -1,31 +1,3 @@
|
|
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_subtitle {
|
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
1
|
.dynamic_report{ :id => report.class_name }
|
30
2
|
- if report.title
|
31
3
|
%h2.report_title
|
@@ -40,18 +12,19 @@
|
|
40
12
|
%tr.report_header_row
|
41
13
|
- report.columns.each do |column|
|
42
14
|
%th
|
43
|
-
|
15
|
+
- if column.is_a?(Hash)
|
16
|
+
- if column.keys.include?(:heading)
|
17
|
+
= options[:titleize] ? titleize(column[:heading]) : column[:heading]
|
18
|
+
-else
|
19
|
+
= options[:titleize] ? titleize(column.values.first) : column.values.first
|
20
|
+
-else
|
21
|
+
= options[:titleize] ? titleize(column) : column
|
44
22
|
%tbody.report_body
|
45
23
|
- report.records.each do |record|
|
46
24
|
%tr.report_row
|
47
25
|
- report.columns.each do |column|
|
48
26
|
%td
|
49
|
-
|
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
|
27
|
+
= (options[:commas] == true) ? commify(linkcheck(record,column)) : linkcheck(record,column)
|
55
28
|
|
56
29
|
- if report.charts && report.charts.class === Hash
|
57
30
|
- report.charts.each_pair do |name, chart|
|
@@ -59,4 +32,3 @@
|
|
59
32
|
%h2
|
60
33
|
= name
|
61
34
|
%img{:src => chart_url(chart), :alt => name}
|
62
|
-
|
@@ -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"
|
@@ -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
|
File without changes
|
data/test/test_helper.rb
ADDED
@@ -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
CHANGED
@@ -1,33 +1,37 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynamic_reports
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
- Wayne E. Seguin
|
7
|
+
- Wayne E. Seguin
|
8
|
+
- Joshua Lippiner
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
12
|
|
12
|
-
date: 2009-
|
13
|
+
date: 2009-07-01 00:00:00 -04:00
|
13
14
|
default_executable:
|
14
15
|
dependencies: []
|
15
16
|
|
16
|
-
description: Dynamic Ruby Reporting Engine with support for Charts
|
17
|
+
description: Dynamic Ruby Reporting Engine with support for Charts.
|
17
18
|
email: wayneeseguin@gmail.com, jlippiner@gmail.com
|
18
19
|
executables: []
|
19
20
|
|
20
21
|
extensions: []
|
21
22
|
|
22
|
-
extra_rdoc_files:
|
23
|
-
|
23
|
+
extra_rdoc_files:
|
24
|
+
- README
|
25
|
+
- README.rdoc
|
24
26
|
files:
|
25
27
|
- HISTORY
|
26
28
|
- README
|
27
|
-
- gemspec
|
29
|
+
- dynamic_reports.gemspec
|
30
|
+
- lib/dynamic_reports.rb
|
28
31
|
- lib/dynamic_reports/charts.rb
|
29
32
|
- lib/dynamic_reports/reports.rb
|
30
33
|
- lib/dynamic_reports/templates.rb
|
34
|
+
- lib/dynamic_reports/vendor/google_chart.rb
|
31
35
|
- lib/dynamic_reports/vendor/google_chart/bar_chart.rb
|
32
36
|
- lib/dynamic_reports/vendor/google_chart/base.rb
|
33
37
|
- lib/dynamic_reports/vendor/google_chart/financial_line_chart.rb
|
@@ -35,19 +39,19 @@ files:
|
|
35
39
|
- lib/dynamic_reports/vendor/google_chart/pie_chart.rb
|
36
40
|
- lib/dynamic_reports/vendor/google_chart/scatter_chart.rb
|
37
41
|
- lib/dynamic_reports/vendor/google_chart/venn_diagram.rb
|
38
|
-
- lib/dynamic_reports/
|
42
|
+
- lib/dynamic_reports/views.rb
|
39
43
|
- lib/dynamic_reports/views/default_layout.html.erb
|
40
44
|
- lib/dynamic_reports/views/default_report.html.erb
|
41
45
|
- lib/dynamic_reports/views/default_report.html.haml
|
42
|
-
-
|
43
|
-
- lib/dynamic_reports.rb
|
46
|
+
- README.rdoc
|
44
47
|
has_rdoc: true
|
45
|
-
homepage: http://
|
48
|
+
homepage: http://dynamicreports.rubyforge.org/
|
46
49
|
licenses: []
|
47
50
|
|
48
51
|
post_install_message:
|
49
|
-
rdoc_options:
|
50
|
-
|
52
|
+
rdoc_options:
|
53
|
+
- --inline-source
|
54
|
+
- --charset=UTF-8
|
51
55
|
require_paths:
|
52
56
|
- lib
|
53
57
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -64,10 +68,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
64
68
|
version:
|
65
69
|
requirements: []
|
66
70
|
|
67
|
-
rubyforge_project:
|
68
|
-
rubygems_version: 1.3.
|
71
|
+
rubyforge_project: dynamicreports
|
72
|
+
rubygems_version: 1.3.4
|
69
73
|
signing_key:
|
70
74
|
specification_version: 3
|
71
|
-
summary:
|
72
|
-
test_files:
|
73
|
-
|
75
|
+
summary: Dynamic Ruby Reporting Engine with support for Charts
|
76
|
+
test_files:
|
77
|
+
- test/dynamic_reports/charts_test.rb
|
78
|
+
- test/dynamic_reports/reports_test.rb
|
79
|
+
- test/dynamic_reports/templates_test.rb
|
80
|
+
- test/dynamic_reports/views_test.rb
|
81
|
+
- test/dynamic_reports.rb
|
82
|
+
- test/factories/records.rb
|
83
|
+
- test/test_helper.rb
|
data/gemspec.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
require "rubygems"
|
2
|
-
|
3
|
-
library="dynamic_reports"
|
4
|
-
version="0.0.1"
|
5
|
-
|
6
|
-
Gem::Specification::new do |spec|
|
7
|
-
$VERBOSE = nil
|
8
|
-
spec.name = library
|
9
|
-
spec.summary = library
|
10
|
-
spec.version = version
|
11
|
-
spec.description = "Dynamic Ruby Reporting Engine with support for Charts"
|
12
|
-
spec.platform = Gem::Platform::RUBY
|
13
|
-
spec.files = ["HISTORY", "README", "gemspec.rb", Dir::glob("lib/**/**")].flatten
|
14
|
-
spec.executables = Dir::glob("bin/*").map{ |script| File::basename script }
|
15
|
-
spec.require_path = "lib"
|
16
|
-
spec.has_rdoc = File::exist?("doc")
|
17
|
-
spec.author = "Wayne E. Seguin & Joshua Lippiner"
|
18
|
-
spec.email = "wayneeseguin@gmail.com, jlippiner@gmail.com"
|
19
|
-
spec.homepage = "http://github.com/wayneeseguin/direct_reports"
|
20
|
-
# spec.test_suite_file = "test/#{library}.rb" if File::directory?("test")
|
21
|
-
#spec.add_dependency "", ">= 0.0"
|
22
|
-
spec.extensions << "extconf.rb" if File::exists?("extconf.rb")
|
23
|
-
spec.rubyforge_project = library
|
24
|
-
end
|