wayneeseguin-dynamic_reports 0.0.3 → 0.0.4

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/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
- == Stylizing
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
- You can create your own styles by simply adding a class_name object to the report definition as such:
123
-
124
- class OrdersReport < DynamicReports::Report
125
- title "Orders Report"
126
- subtitle "All orders recorded in database"
127
- columns :total, :created_at
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
- class_name "my_class_name"
130
- end
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
- This will cause DR to simply not include the inline style. From there you can customer the styles using the
133
- following sub-classes for your class name, for example:
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
- .my_class_name .report_title {}
136
- .my_class_name .report_subtitle {}
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
- == Rails Usage
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 (And his friend :))
240
+ * Kenneth Kalmer & Nic Young
183
241
  * Yehuda Katz
184
242
 
185
243
  For their encouragement, feedback and advise.
data/README.rdoc 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
- == Stylizing
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
- You can create your own styles by simply adding a class_name object to the report definition as such:
123
-
124
- class OrdersReport < DynamicReports::Report
125
- title "Orders Report"
126
- subtitle "All orders recorded in database"
127
- columns :total, :created_at
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
- class_name "my_class_name"
130
- end
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
- This will cause DR to simply not include the inline style. From there you can customer the styles using the
133
- following sub-classes for your class name, for example:
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
- .my_class_name .report_title {}
136
- .my_class_name .report_subtitle {}
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
- == Rails Usage
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 (And his friend :))
240
+ * Kenneth Kalmer & Nic Young
183
241
  * Yehuda Katz
184
242
 
185
243
  For their encouragement, feedback and advise.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{dynamic_reports}
5
- s.version = "0.0.3"
5
+ s.version = "0.0.4"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Wayne E. Seguin", "Joshua Lippiner"]
@@ -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
- # Load all defined reports.
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
@@ -170,6 +170,50 @@ module DynamicReports
170
170
  chart_options = chart_options.shift || {}
171
171
  charts(Chart.configure(name, chart_options, &block))
172
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
173
217
 
174
218
  # Method for instanciating a report instance on a set of given records.
175
219
  #
@@ -187,14 +231,6 @@ module DynamicReports
187
231
  def on(records)
188
232
  new(records, @options)
189
233
  end
190
-
191
- #--
192
- # Methods for definining a sub report
193
- #def link_column
194
- #end
195
- #def link_rows
196
- #end
197
-
198
234
  end
199
235
 
200
236
  # Instantiate the report on a set of records.
@@ -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,73 +1,42 @@
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
1
  <div id="<%= report.class_name %>" class="dynamic_report">
33
2
  <%= "<div class='report_title'>#{report.title}</div>" if report.title %>
34
- <%= "<div class='report_sub_title'>#{report.sub_title}</div>" if report.sub_title %>
3
+ <%= "<div class='report_subtitle'>#{report.sub_title}</div>" if report.sub_title %>
35
4
  <table class="report" border="0" cellpadding="0" cellspacing="0">
36
5
  <thead class="report_header">
37
6
  <tr class="report_header_row">
38
7
  <% report.columns.each do |column| %>
39
- <th>
40
- <%= options[:titleize] ? titleize(column) : column %>
41
- </th>
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
- <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>
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
- <span class="report_chart">
67
- <%= "<img src='#{chart_url(chart,report)}' alt='#{chart.name}'>" %>
68
- </span>
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_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
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
- = options[:titleize] ? titleize(column) : column
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
- - 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
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
-
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wayneeseguin-dynamic_reports
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wayne E. Seguin
@@ -46,6 +46,7 @@ files:
46
46
  - README.rdoc
47
47
  has_rdoc: false
48
48
  homepage: http://dynamicreports.rubyforge.org/
49
+ licenses:
49
50
  post_install_message:
50
51
  rdoc_options:
51
52
  - --inline-source
@@ -67,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
68
  requirements: []
68
69
 
69
70
  rubyforge_project: dynamicreports
70
- rubygems_version: 1.2.0
71
+ rubygems_version: 1.3.5
71
72
  signing_key:
72
73
  specification_version: 3
73
74
  summary: Dynamic Ruby Reporting Engine with support for Charts