compendium 1.1.3.4 → 1.2.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.
- checksums.yaml +5 -13
- data/.travis.yml +12 -0
- data/CHANGELOG.md +18 -0
- data/Gemfile +4 -0
- data/README.md +185 -4
- data/app/assets/stylesheets/compendium/options.css.scss +2 -3
- data/app/classes/compendium/presenters/chart.rb +1 -1
- data/app/classes/compendium/presenters/csv.rb +32 -0
- data/app/classes/compendium/presenters/query.rb +4 -2
- data/app/classes/compendium/presenters/settings/query.rb +10 -2
- data/app/classes/compendium/presenters/settings/table.rb +24 -4
- data/app/classes/compendium/presenters/table.rb +33 -18
- data/app/controllers/compendium/reports_controller.rb +28 -7
- data/app/views/compendium/reports/setup.haml +16 -2
- data/compendium.gemspec +4 -3
- data/config/locales/en.yml +6 -1
- data/config/locales/es.yml +11 -0
- data/config/locales/fr.yml +11 -0
- data/lib/compendium.rb +1 -0
- data/lib/compendium/collection_query.rb +1 -1
- data/lib/compendium/count_query.rb +7 -1
- data/lib/compendium/dsl.rb +45 -4
- data/lib/compendium/engine/mount.rb +13 -5
- data/lib/compendium/errors.rb +6 -0
- data/lib/compendium/metric.rb +1 -1
- data/lib/compendium/open_hash.rb +1 -1
- data/lib/compendium/param_types.rb +2 -2
- data/lib/compendium/params.rb +1 -1
- data/lib/compendium/query.rb +23 -4
- data/lib/compendium/report.rb +14 -10
- data/lib/compendium/sum_query.rb +3 -1
- data/lib/compendium/through_query.rb +7 -2
- data/lib/compendium/version.rb +1 -1
- data/spec/count_query_spec.rb +41 -5
- data/spec/dsl_spec.rb +77 -2
- data/spec/presenters/csv_spec.rb +30 -0
- data/spec/presenters/settings/query_spec.rb +26 -0
- data/spec/presenters/settings/table_spec.rb +64 -0
- data/spec/presenters/table_spec.rb +83 -0
- data/spec/query_spec.rb +55 -8
- data/spec/report_spec.rb +24 -1
- data/spec/sum_query_spec.rb +40 -5
- metadata +73 -30
- data/config/initializers/ruby/hash.rb +0 -6
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
MWEzM2NiMjk2ZjhiNGE5YmIwNjkzNjY0MTRkMDI1YWU3OGE1NWE3Ng==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a4bf2931ee1fe86a8844273e9219577c865fa9e7
|
4
|
+
data.tar.gz: 5f75cd47f1a38914d32850ce28b37341a536c36e
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
YzI2YTY0NGYzODdmOGFkNmI1NTBmMDVmNzBjZTI3ODBiMDdlMzJiZDk3OWZk
|
11
|
-
NDhjMjk2NDlmZTdkOTJkMTc3NWJjZGE1ZTcxZGQ0N2RkODNiODE=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
ZGMzNzk4NGVhMDU0NjU1MDVjNGYyYzM2ZjIyMWZjOTc5MzgwMDEyNWEzYzcz
|
14
|
-
NTgwZGQ2OTA0YTMwNDZhYTAyYWNlMWQ1MGYzZDM0ZWQ3YTRmODE0MzAzMDUy
|
15
|
-
MzNlYjQ0NDNiZGJlMDViOTQ0NDRmNDcwMDc5MTJiNWMzYTk0NzY=
|
6
|
+
metadata.gz: '09afd485514be265abc5af4600fad2ef3054650160ea351658ea27aa325e3b90e9b81b88d138394568bb5abf652d79cb90e40907662f739503d3a4cf4a31be7a'
|
7
|
+
data.tar.gz: 8eb6644a34e973139131469c3c069fbd518f62ed7bd3ba0afebebeb8ea27a09f1d6f8a9da433ec62987d7c814ddb08d588b433ef888adfad98e5b3e2b86c1d8d
|
data/.travis.yml
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 1.2.0
|
4
|
+
* Added the ability to render a query to CSV, and a controller action for downloading the CSV
|
5
|
+
* Added `exports` report setting
|
6
|
+
* Added `skip_totals_for` option to table settings to define columns to skip in the totals row
|
7
|
+
* Added `i18n_scope` option to table settings
|
8
|
+
* Added `Settings::Query#update` to update query settings with a block
|
9
|
+
* Allow table settings to be specified on the report object
|
10
|
+
* Add settings to `render_table` to specify the CSS classes to use for each element.
|
11
|
+
* Allow queries to be ordered and reversed via query options (:order and :reverse)
|
12
|
+
* Add default orders for count and sum queries
|
13
|
+
* Fix redefining a query so that it actually overrides the previous query instead of creating a new one with the same name
|
14
|
+
|
15
|
+
## 1.1.3
|
16
|
+
* Add `SumQuery` query type
|
17
|
+
* Fix option tooltip covering input elements in IE [rvracaric]
|
18
|
+
* Allow custom param validations to be specified
|
19
|
+
* Fix filters being overridden by subclassed queries
|
20
|
+
|
3
21
|
## 1.1.2
|
4
22
|
* Allow direct access to a chart object without having to render it (useful if the provider allows chart settings to be updated after initialization)
|
5
23
|
* Delegate missing methods from ChartProvider classes to the chart
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Compendium [](http://badge.fury.io/rb/compendium)
|
1
|
+
# Compendium [](http://badge.fury.io/rb/compendium) [](https://travis-ci.org/dvandersluis/compendium)
|
2
2
|
|
3
3
|
Ruby on Rails framework for making reporting easy.
|
4
4
|
|
@@ -63,6 +63,89 @@ Compendium also comes with a variety of different presenters, for rendering the
|
|
63
63
|
(`report.render_chart`), tables (`report.render_table`) and metrics for your report. Charting is delegated through a
|
64
64
|
`ChartProvider` to a charting gem (amcharts.rb is currently supported).
|
65
65
|
|
66
|
+
### Report Options
|
67
|
+
Report options are defined by the keyword `option` in your report class. Options must have a name and a type (scalar, boolean, date, dropdown or radio). Additionally, an option can have a default value (given by a proc passed in with the `default:` key), and validations (via the `validates:` key).
|
68
|
+
|
69
|
+
In order to specify parameters for the options, pass a hash to `MyReport.new`. Parameters are available via `params`:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
r = MyReport.new(starting_on: Date.today - 3.months, ending_on: Date.today)
|
73
|
+
r.params
|
74
|
+
|
75
|
+
# {
|
76
|
+
# "starting_on"=>Sun, 30 Aug 2015,
|
77
|
+
# "ending_on"=>Mon, 30 Nov 2015,
|
78
|
+
# }
|
79
|
+
```
|
80
|
+
|
81
|
+
#### Validation
|
82
|
+
|
83
|
+
If validation is set up on any options, calling `valid?` on the report will validate any given parameters against the validations set up, and will populate an errors object. All validations provided by `ActiveModel::Validations` are available.
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
class MyReport < Compendium::Report
|
87
|
+
options :starting_on, :date, validates: { presence: true }
|
88
|
+
end
|
89
|
+
|
90
|
+
r = MyReport.new
|
91
|
+
r.valid?
|
92
|
+
# => false
|
93
|
+
|
94
|
+
r.errors
|
95
|
+
# => #<ActiveModel::Errors:0x007fe8359cc6b8
|
96
|
+
# @base={"starting_on"=>nil},
|
97
|
+
# @messages={:starting_on=>["This field is required."]}>
|
98
|
+
```
|
99
|
+
|
100
|
+
### Query types
|
101
|
+
|
102
|
+
Compendium provides a few types of queries in order to make report writing more streamlined.
|
103
|
+
|
104
|
+
#### Through Queries
|
105
|
+
|
106
|
+
A **through query** lets you use the results of a previous query (or multiple queries) as the basis of your query. This lets you build on another query or combine multiple query's results into a single query. It it specified by passing the `through:` key to `query`, with a query name or array or query names (as symbols).
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
query :dog_sales { |params| Order.where(pet_type: 'dog', created_at: params[:starting_on]..params[:ending_on]) }
|
110
|
+
query :cat_sales { |params| Order.where(pet_type: 'cat', created_at: params[:starting_on]..params[:ending_on]) }
|
111
|
+
query :bird_sales { |params| Order.where(pet_type: 'bird', created_at: params[:starting_on]..params[:ending_on]) }
|
112
|
+
|
113
|
+
query :total_sales, through: [:dog_sales, :cat_sales, :bird_sales] do |results, params|
|
114
|
+
# results is a hash with keys :dog_sales, :cat_sales, :bird_sales
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
#### Count Queries
|
119
|
+
|
120
|
+
A **count query** simplifies creating a query where you want a count (especially per group of something). A count query is specified by adding `count: true` to the `query` call.
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
query :sales_per_day, count: true do
|
124
|
+
Order.group("DATE(created_at)")
|
125
|
+
end
|
126
|
+
|
127
|
+
# results will look something like
|
128
|
+
# { 2015-10-01 => 4, 2015-10-02 => 20, ... }
|
129
|
+
```
|
130
|
+
|
131
|
+
#### Sum Queries
|
132
|
+
|
133
|
+
Like a count query, a **sum query** is useful for performing an aggregate function on a grouped query, in this case summing the results. A sum query is specified by adding <code>sum: <i>:column_name</i></code> to the `query` call.
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
query :commission_per_salesperson, sum: 'commission' do
|
137
|
+
# assume commission is a numeric column
|
138
|
+
Order.group(:employee_id)
|
139
|
+
end
|
140
|
+
|
141
|
+
# results will be something like
|
142
|
+
# { 1 => 840.34, 2 => 1065.02, ... }
|
143
|
+
```
|
144
|
+
|
145
|
+
#### Collection Queries
|
146
|
+
|
147
|
+
Sometimes you'll want to run a collection over a collection of data; for this, you can use a **collection query**. A collection query will perform the same query for each element of a hash or array, or for each result of a query. A collection is specified via `collection: [...]`, `collection: { ... }` or `collection: query` (note not a symbol but an actual query object).
|
148
|
+
|
66
149
|
### Tying into your Rails application
|
67
150
|
|
68
151
|
Compendium has a `Rails::Engine`, which adds a default controller and some views. If desired, the controller can be
|
@@ -78,14 +161,37 @@ within your `config/routes.rb` file
|
|
78
161
|
mount_compendium at: '/report', controller: 'reports' # controller defaults to compendium/reports
|
79
162
|
```
|
80
163
|
|
81
|
-
### Rendering report results
|
164
|
+
### Rendering report results in other formats
|
165
|
+
|
166
|
+
#### JSON
|
82
167
|
|
83
168
|
While the default action when running a report is to render a view with the results, Compendium reports can be rendered
|
84
169
|
as JSON. If using the default routes provided by `mount_compendium` (assuming compendium was mounted at `/report`),
|
85
|
-
`POST`ing to <code>report/<i>report_name</i>.json</code> will return the report results as JSON. You can also collect
|
86
|
-
the results of a single query (instead of the entire report) by `POST`ing to
|
170
|
+
`GET`ing or `POST`ing to <code>report/<i>report_name</i>.json</code> will return the report results as JSON. You can also collect
|
171
|
+
the results of a single query (instead of the entire report) by `GET`ing or `POST`ing to
|
87
172
|
<code>report/<i>report_name</i>/<i>query_name</i>.json</code>.
|
88
173
|
|
174
|
+
#### CSV
|
175
|
+
|
176
|
+
A report can be exported as CSV. In order to enable CSV exports, a query needs to be defined as the exporter
|
177
|
+
for the report. Note that only one query can be exported, because otherwise there's no way to ensure that the
|
178
|
+
headings are consistent.
|
179
|
+
|
180
|
+
```ruby
|
181
|
+
class MyReport < Compendium::Report
|
182
|
+
exports :csv, :deliveries # Defines `deliveries` to be the query that is exported to CSV
|
183
|
+
end
|
184
|
+
```
|
185
|
+
|
186
|
+
Note that if your report class subclasses another, and you want to disable a previously defined exporter, you can with `exports :csv, false`.
|
187
|
+
|
188
|
+
When a report has a CSV exporter defined, an `Export CSV` button will appear on the default setup page. You can also directly export
|
189
|
+
using the path `/report/:report_name/export.csv` (using `GET` or `POST`).
|
190
|
+
|
191
|
+
Customization of the query can be done by setting table options for the query. See the [Rendering a table](#rendering-a-table) section below for more details.
|
192
|
+
|
193
|
+
## Displaying Report Results
|
194
|
+
|
89
195
|
### Chart Providers
|
90
196
|
|
91
197
|
As of 1.1.0, chart providers have been extracted out of the main repository and are available as their own gems. If you want to render queries as a chart, a chart provider gem is needed.
|
@@ -100,6 +206,81 @@ end
|
|
100
206
|
|
101
207
|
The following providers are available (If you would like to contribute a chart provider, please let me know and I'll add it to the list):
|
102
208
|
* [compendium-amcharts](https://github.com/dvandersluis/compendium-amcharts) - makes use of [AmCharts.rb](https://github.com/dvandersluis/amcharts.rb)
|
209
|
+
* [compendium-highcharts](https://github.com/cimtico/compendium-highcharts) - makes use of [lazy_high_charts](https://github.com/michelson/lazy_high_charts) [thanks to [cimtico](https://github.com/cimtico)]
|
210
|
+
|
211
|
+
### Rendering a table
|
212
|
+
|
213
|
+
> *Note: When table settings are defined for a query, they are applied both to rendering HTML tables, as well as CSV file exports.
|
214
|
+
See [Rendering report results in other formats](#rendering-report-results-in-other-formats) above for more details.*
|
215
|
+
|
216
|
+
In addition to charts, you can output a query as a table. When a query is rendered as a table, each row is output with columns in the
|
217
|
+
query order (so you may want to use an explicit `select` in your query to order the columns as required). If the query is set up with
|
218
|
+
`totals: true`, a totals row will be added to the bottom of the table.
|
219
|
+
|
220
|
+
In order to customize the table, you can add a `table` declaration to your report. Each query can have different table settings.
|
221
|
+
|
222
|
+
```ruby
|
223
|
+
class MyReport < Compendium::Report
|
224
|
+
table :deliveries do
|
225
|
+
# The i18n scope to use for any translations can be specified:
|
226
|
+
i18n_scope 'reports.my_report'
|
227
|
+
|
228
|
+
# Column headings by default are the column name passed through I18n,
|
229
|
+
# but can be overridden:
|
230
|
+
|
231
|
+
# ... with a block...
|
232
|
+
override_heading do |heading|
|
233
|
+
# ...
|
234
|
+
end
|
235
|
+
|
236
|
+
# ... or one at a time...
|
237
|
+
override_heading :col, 'My Column'
|
238
|
+
|
239
|
+
# Records where a cell is 0 or nil can have the value overridden to something else:
|
240
|
+
display_zero_as 'N/A'
|
241
|
+
display_nil_as 'NULL'
|
242
|
+
|
243
|
+
# You can specify how to format numbers:
|
244
|
+
number_format "%0.1f"
|
245
|
+
|
246
|
+
# You can also specify formatting on a per-column basis:
|
247
|
+
format(:col) do |value|
|
248
|
+
"#{(value / 50) * 100}%"
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
```
|
253
|
+
|
254
|
+
A query is rendered from a view, and is passed in the view context as the first parameter. Optionally, a block can be passed to
|
255
|
+
override previously defined settings:
|
256
|
+
|
257
|
+
```ruby
|
258
|
+
my_query.render_table(self) do
|
259
|
+
display_zero_as 'nil' # Override the previous version just for this render
|
260
|
+
end
|
261
|
+
```
|
262
|
+
|
263
|
+
#### CSS Classes
|
264
|
+
|
265
|
+
By default, Compendium uses the following four CSS classes when rendering a table:
|
266
|
+
|
267
|
+
| Element | Element Type | Class Name |
|
268
|
+
|-----------------------|--------------|------------|
|
269
|
+
| Table | `table` | `results` |
|
270
|
+
| Table header | `tr` | `headings` |
|
271
|
+
| Table data | `tr` | `data` |
|
272
|
+
| Table footer (totals) | `tr` | `totals` |
|
273
|
+
|
274
|
+
Each class can be overridden when setting up the table:
|
275
|
+
|
276
|
+
```ruby
|
277
|
+
my_query.render_table(self) do |t|
|
278
|
+
t.table_class 'my_table_class'
|
279
|
+
t.header_class 'my_header_class'
|
280
|
+
t.row_class 'my_row_class'
|
281
|
+
t.totals_class 'my_totals_class'
|
282
|
+
end
|
283
|
+
```
|
103
284
|
|
104
285
|
### Interaction with other gems
|
105
286
|
* If [accessible_tooltip](https://github.com/dvandersluis/accessible_tooltip) is present, option notes will be rendered
|
@@ -48,7 +48,7 @@ module Compendium::Presenters
|
|
48
48
|
params = {}
|
49
49
|
params[:report] = options[:params] if options[:params]
|
50
50
|
|
51
|
-
if remote?
|
51
|
+
if remote? && protected_against_csrf?
|
52
52
|
# If we're loading remotely, and CSRF protection is enabled,
|
53
53
|
# automatically include the CSRF token in AJAX params
|
54
54
|
params.merge!(form_authenticity_param)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
module Compendium::Presenters
|
4
|
+
class CSV < Table
|
5
|
+
def initialize(object, &block)
|
6
|
+
super(nil, object, &block)
|
7
|
+
end
|
8
|
+
|
9
|
+
def render
|
10
|
+
::CSV.generate do |csv|
|
11
|
+
csv << headings.map{ |_, val| formatted_heading(val) }
|
12
|
+
|
13
|
+
records.each do |row|
|
14
|
+
csv << row.map{ |key, val| formatted_value(key, val) }
|
15
|
+
end
|
16
|
+
|
17
|
+
if has_totals_row?
|
18
|
+
totals[totals.keys.first] = translate(:total)
|
19
|
+
csv << totals.map do |key, val|
|
20
|
+
formatted_value(key, val) unless settings.skipped_total_cols.include?(key.to_sym)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def settings_class
|
29
|
+
Compendium::Presenters::Settings::Table
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'compendium/presenters/base'
|
2
|
+
require 'compendium/presenters/settings/query'
|
3
|
+
require 'compendium/presenters/settings/table'
|
2
4
|
|
3
5
|
module Compendium::Presenters
|
4
6
|
class Query < Base
|
@@ -19,7 +21,7 @@ module Compendium::Presenters
|
|
19
21
|
end
|
20
22
|
|
21
23
|
def settings_class
|
22
|
-
Settings.const_get(self.class.name.demodulize) rescue Settings::Query
|
24
|
+
Settings.const_get(self.class.name.demodulize, false) rescue Settings::Query
|
23
25
|
end
|
24
26
|
end
|
25
|
-
end
|
27
|
+
end
|
@@ -1,9 +1,17 @@
|
|
1
1
|
module Compendium::Presenters::Settings
|
2
2
|
class Query
|
3
|
+
attr_reader :query
|
4
|
+
|
3
5
|
delegate :[], :fetch, to: :@settings
|
6
|
+
delegate :report, to: :query, allow_nil: true
|
4
7
|
|
5
|
-
def initialize
|
8
|
+
def initialize(query = nil)
|
6
9
|
@settings = {}.with_indifferent_access
|
10
|
+
@query = query
|
11
|
+
end
|
12
|
+
|
13
|
+
def update(&block)
|
14
|
+
instance_exec(self, &block)
|
7
15
|
end
|
8
16
|
|
9
17
|
def method_missing(name, *args, &block)
|
@@ -19,4 +27,4 @@ module Compendium::Presenters::Settings
|
|
19
27
|
end
|
20
28
|
end
|
21
29
|
end
|
22
|
-
end
|
30
|
+
end
|
@@ -1,16 +1,32 @@
|
|
1
|
+
require 'compendium/presenters/settings/query'
|
2
|
+
|
1
3
|
module Compendium::Presenters::Settings
|
2
4
|
class Table < Query
|
3
5
|
attr_reader :headings
|
4
6
|
|
5
|
-
def initialize(
|
6
|
-
super
|
7
|
+
def initialize(*)
|
8
|
+
super
|
9
|
+
|
10
|
+
@headings = {}
|
11
|
+
|
12
|
+
# Set default values for settings
|
13
|
+
number_format '%0.2f'
|
14
|
+
table_class 'results'
|
15
|
+
header_class 'headings'
|
16
|
+
row_class 'data'
|
17
|
+
totals_class 'totals'
|
18
|
+
skipped_total_cols []
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_headings(headings)
|
22
|
+
headings.map!(&:to_sym)
|
7
23
|
@headings = Hash[headings.zip(headings)].with_indifferent_access
|
8
24
|
end
|
9
25
|
|
10
26
|
def override_heading(*args, &block)
|
11
27
|
if block_given?
|
12
28
|
@headings.each do |key, val|
|
13
|
-
res = yield val
|
29
|
+
res = yield val.to_s
|
14
30
|
@headings[key] = res if res
|
15
31
|
end
|
16
32
|
else
|
@@ -27,5 +43,9 @@ module Compendium::Presenters::Settings
|
|
27
43
|
def formatters
|
28
44
|
(@settings[:formatters] || {})
|
29
45
|
end
|
46
|
+
|
47
|
+
def skip_total_for(*cols)
|
48
|
+
@settings[:skipped_total_cols].concat(cols.map(&:to_sym))
|
49
|
+
end
|
30
50
|
end
|
31
|
-
end
|
51
|
+
end
|
@@ -1,27 +1,33 @@
|
|
1
1
|
module Compendium::Presenters
|
2
2
|
class Table < Query
|
3
|
-
attr_reader :records, :totals
|
3
|
+
attr_reader :records, :totals, :settings
|
4
4
|
|
5
5
|
def initialize(*)
|
6
6
|
super
|
7
7
|
|
8
8
|
@records = results.records
|
9
|
-
@totals = @records.pop if has_totals_row?
|
10
9
|
|
11
|
-
@settings = settings_class.new(
|
10
|
+
@settings = settings_class.new(query)
|
11
|
+
@settings.set_headings(results.keys)
|
12
|
+
@settings.update(&query.table_settings) if query.table_settings
|
12
13
|
yield @settings if block_given?
|
14
|
+
|
15
|
+
if has_totals_row?
|
16
|
+
@totals = @records.pop
|
17
|
+
totals[totals.keys.first] = translate(:total)
|
18
|
+
end
|
13
19
|
end
|
14
20
|
|
15
21
|
def render
|
16
|
-
content_tag(:table, class:
|
22
|
+
content_tag(:table, class: @settings.table_class) do
|
17
23
|
table = ActiveSupport::SafeBuffer.new
|
18
|
-
table << content_tag(:thead,
|
24
|
+
table << content_tag(:thead, build_row(headings, settings.header_class, :th, &heading_proc))
|
19
25
|
table << content_tag(:tbody) do
|
20
26
|
tbody = ActiveSupport::SafeBuffer.new
|
21
|
-
records.each { |row| tbody <<
|
27
|
+
records.each { |row| tbody << build_row(row, settings.row_class, &data_proc) }
|
22
28
|
tbody
|
23
29
|
end
|
24
|
-
table << content_tag(:tfoot,
|
30
|
+
table << content_tag(:tfoot, build_row(totals, @settings.totals_class, :th, &totals_proc)) if has_totals_row?
|
25
31
|
table
|
26
32
|
end
|
27
33
|
end
|
@@ -36,21 +42,20 @@ module Compendium::Presenters
|
|
36
42
|
query.options.fetch(:totals, false)
|
37
43
|
end
|
38
44
|
|
39
|
-
def
|
40
|
-
|
45
|
+
def data_proc
|
46
|
+
proc { |key, val| formatted_value(key, val) }
|
41
47
|
end
|
42
48
|
|
43
|
-
def
|
44
|
-
|
49
|
+
def heading_proc
|
50
|
+
proc { |_, val| formatted_heading(val) }
|
45
51
|
end
|
46
52
|
|
47
|
-
def
|
48
|
-
|
49
|
-
build_row(totals, 'totals', :th) { |key, val| formatted_value(key, val) }
|
53
|
+
def totals_proc
|
54
|
+
proc { |key, val| formatted_value(key, val) unless settings.skipped_total_cols.include?(key.to_sym) }
|
50
55
|
end
|
51
56
|
|
52
57
|
def build_row(row, row_class, cell_type = :td)
|
53
|
-
content_tag(
|
58
|
+
content_tag(:tr, class: row_class) do
|
54
59
|
out = ActiveSupport::SafeBuffer.new
|
55
60
|
|
56
61
|
row.each.with_index do |(key, val), i|
|
@@ -62,20 +67,30 @@ module Compendium::Presenters
|
|
62
67
|
end
|
63
68
|
end
|
64
69
|
|
70
|
+
def formatted_heading(v)
|
71
|
+
v.is_a?(Symbol) ? translate(v) : v
|
72
|
+
end
|
73
|
+
|
65
74
|
def formatted_value(k, v)
|
66
75
|
if @settings.formatters[k]
|
67
76
|
@settings.formatters[k].call(v)
|
68
77
|
else
|
69
78
|
if v.numeric?
|
70
|
-
if v.zero?
|
79
|
+
if v.zero? && @settings.display_zero_as?
|
71
80
|
@settings.display_zero_as
|
72
81
|
else
|
73
|
-
sprintf(@settings.number_format
|
82
|
+
sprintf(@settings.number_format, v)
|
74
83
|
end
|
75
84
|
elsif v.nil?
|
76
85
|
@settings.display_nil_as
|
77
86
|
end
|
78
87
|
end || v
|
79
88
|
end
|
89
|
+
|
90
|
+
def translate(v, opts = {})
|
91
|
+
opts.reverse_merge!(scope: settings.i18n_scope) if settings.i18n_scope?
|
92
|
+
opts[:default] = -> * { I18n.t(v, scope: 'compendium') }
|
93
|
+
I18n.t(v, opts)
|
94
|
+
end
|
80
95
|
end
|
81
|
-
end
|
96
|
+
end
|