compendium 1.0.7 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CHANGELOG.md +18 -0
- data/README.md +10 -0
- data/app/classes/compendium/presenters/chart.rb +43 -8
- data/lib/compendium/abstract_chart_provider.rb +10 -11
- data/lib/compendium/dsl.rb +8 -0
- data/lib/compendium/query.rb +42 -8
- data/lib/compendium/report.rb +20 -0
- data/lib/compendium/version.rb +1 -1
- data/spec/dsl_spec.rb +31 -2
- data/spec/presenters/chart_spec.rb +38 -4
- data/spec/query_spec.rb +51 -2
- data/spec/report_spec.rb +5 -0
- metadata +3 -3
- data/lib/compendium/chart_provider/amcharts.rb +0 -20
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YzRhZmU5NjE5ZTIzMGZmM2JmMzhlNDRhNjY3NTQ2ZjRjYzI0ZDkxNg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ODk2NGYxNjU1YzgzZTlkZmM5MmU1ZjljZjNlNjdkZGE1YTY0ZmY1Ng==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
OThmYTFhNmQ2MWY0NTdmYmQxYzg2OTkzYzViNThmMTNjNzhhNDgzMjU4NmQ2
|
10
|
+
NjYyMThlMzQyMDY4NzU1YWY0MTdiNGIyYWFjNzdlMzgzMGMyZjY0MTk0MjU2
|
11
|
+
MzEyYTVjMGE1ZTQ2NTczN2YyOWM5ZTg1YTk1Mzg3ZjYxOTNjOGI=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
Y2M1NzdhOGQzMWVhZjNmNGVlZTVlY2JiOWQzZTFlZTkzZGY4ZjE5YjdiMWVi
|
14
|
+
ZGU2MzY3ZTU4ZTFiNzU4MDQxNTA5ZjBlZTlmY2YyNGIyM2ZlZWQ3MzNhYzMz
|
15
|
+
ZjExMWFhOWZhZTIwOGQwZjJlOGQ2ZGE1OTFhYjAxOTA2MzEwMGE=
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Change Log
|
2
|
+
|
3
|
+
## 1.1.0 (unreleased)
|
4
|
+
* Added query filters (allow a result set to be filtered to remove/translate/etc. data)
|
5
|
+
* Extract chart providers into their own gems
|
6
|
+
* Allow queries to be rendered as charts without having been run yet (to set up for a future AJAX load)
|
7
|
+
* Added `Report#url` and `Query#url` methods to get the JSON URL
|
8
|
+
|
9
|
+
## 1.0.7
|
10
|
+
* Added the ability to render a report or a specific query of a report as JSON
|
11
|
+
|
12
|
+
## 1.0.6
|
13
|
+
* Added a built-in renderer for metrics
|
14
|
+
|
15
|
+
## 1.0.5
|
16
|
+
* Fixed the `:only` and `:except` options to `Report#run`
|
17
|
+
* Give `ThroughQuery` access to params if the definition block has an arity of 2
|
18
|
+
* Fixed mutating results in a `ThroughQuery` block affecting the parent query
|
data/README.md
CHANGED
@@ -24,6 +24,16 @@ class MyReport < Compendium::Report
|
|
24
24
|
Items.where(delivered: true, purchased_at: (params[:starting_on]..params[:ending_on]))
|
25
25
|
end
|
26
26
|
|
27
|
+
# Define a filter to modify the results from specified query (in this case :deliveries)
|
28
|
+
# For example, this can be useful to translate columns prior to rendering, as it will apply
|
29
|
+
# for all render types (table, chart, JSON)
|
30
|
+
# Note: A filter can be applied to multiple queries at once
|
31
|
+
filter :deliveries do |results, params|
|
32
|
+
results.each do |row|
|
33
|
+
row['price'] = sprintf('$%.2f', row['price'])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
27
37
|
# Define a query which collects data by using AR directly
|
28
38
|
query :on_hand_inventory, collect: :active_record do |params|
|
29
39
|
Items.where(in_stock: true)
|
@@ -3,17 +3,25 @@ require 'active_support/core_ext/array/extract_options'
|
|
3
3
|
|
4
4
|
module Compendium::Presenters
|
5
5
|
class Chart < Query
|
6
|
-
attr_reader :data, :container, :chart_provider
|
6
|
+
attr_reader :data, :params, :container, :chart_provider
|
7
|
+
attr_accessor :options
|
7
8
|
|
8
9
|
def initialize(template, object, *args, &setup)
|
9
|
-
options = args.extract_options!
|
10
|
-
type, container = args
|
11
|
-
|
12
10
|
super(template, object)
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
self.options = args.extract_options!
|
13
|
+
type, container = args
|
14
|
+
|
15
|
+
if remote?
|
16
|
+
# If the query hasn't run yet, render a chart that loads its data remotely (ie. through AJAX)
|
17
|
+
# ie. if rendering a query from a report class directly
|
18
|
+
@data = query.url
|
19
|
+
@params = collect_params
|
20
|
+
else
|
21
|
+
@data = options[:index] ? results.records[options[:index]] : results
|
22
|
+
@data = @data.records if @data.is_a?(Compendium::ResultSet)
|
23
|
+
@data = @data[0...-1] if query.options[:totals]
|
24
|
+
end
|
17
25
|
|
18
26
|
@container = container || query.name
|
19
27
|
|
@@ -32,7 +40,34 @@ module Compendium::Presenters
|
|
32
40
|
end
|
33
41
|
|
34
42
|
def initialize_chart_provider(type, &setup)
|
35
|
-
@chart_provider = provider.new(type, @data, &setup)
|
43
|
+
@chart_provider = provider.new(type, @data, @params, &setup)
|
44
|
+
end
|
45
|
+
|
46
|
+
def collect_params
|
47
|
+
params = {}
|
48
|
+
params[:report] = options[:params] if options[:params]
|
49
|
+
|
50
|
+
if remote? and protected_against_csrf?
|
51
|
+
# If we're loading remotely, and CSRF protection is enabled,
|
52
|
+
# automatically include the CSRF token in AJAX params
|
53
|
+
params.merge!(form_authenticity_param)
|
54
|
+
end
|
55
|
+
|
56
|
+
params
|
57
|
+
end
|
58
|
+
|
59
|
+
# You can force the chart to render remote data, even if the query has already run by passing the remote: true option
|
60
|
+
def remote?
|
61
|
+
!query.ran? || options.fetch(:remote, false)
|
62
|
+
end
|
63
|
+
|
64
|
+
def protected_against_csrf?
|
65
|
+
!@template.controller.forgery_protection_strategy.nil?
|
66
|
+
end
|
67
|
+
|
68
|
+
def form_authenticity_param
|
69
|
+
return {} unless protected_against_csrf?
|
70
|
+
{ @template.controller.request_forgery_protection_token => @template.controller.send(:form_authenticity_token) }
|
36
71
|
end
|
37
72
|
end
|
38
73
|
end
|
@@ -3,10 +3,17 @@ require 'active_support/core_ext/string/inflections'
|
|
3
3
|
module Compendium
|
4
4
|
# Abstract wrapper for rendering charts
|
5
5
|
# To add a new chart provider, #initialize and #render must be implemented
|
6
|
+
# Custom providers should also override Compendium::AbstractChartProvider.find_chart_provider (but fallback to super)
|
7
|
+
|
6
8
|
class AbstractChartProvider
|
7
9
|
attr_reader :chart
|
8
10
|
|
9
|
-
|
11
|
+
# @param type [Symbol] The type of chart you want to render (:pie, :line, etc).
|
12
|
+
# Accepted types might vary by provider.
|
13
|
+
# @param data_or_url [Enumerable or String] The data or URL to the data you wish to render.
|
14
|
+
# Providers may not support loading data remotely.
|
15
|
+
# @param params [Hash] If data_or_url is a URL, the params to use for the AJAX request
|
16
|
+
def initialize(type, data_or_url, params = {}, &setup_proc)
|
10
17
|
raise NotImplementedError
|
11
18
|
end
|
12
19
|
|
@@ -14,17 +21,9 @@ module Compendium
|
|
14
21
|
raise NotImplementedError
|
15
22
|
end
|
16
23
|
|
17
|
-
#
|
24
|
+
# Chart providers need to override this method to add a hook for themselves
|
18
25
|
def self.find_chart_provider
|
19
|
-
|
20
|
-
:AmCharts
|
21
|
-
else
|
22
|
-
self.name.demodulize.to_sym
|
23
|
-
end
|
26
|
+
nil
|
24
27
|
end
|
25
28
|
end
|
26
|
-
|
27
|
-
module ChartProvider
|
28
|
-
autoload :AmCharts, 'compendium/chart_provider/amcharts'
|
29
|
-
end
|
30
29
|
end
|
data/lib/compendium/dsl.rb
CHANGED
@@ -49,6 +49,13 @@ module Compendium
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
+
def filter(*query_names, &block)
|
53
|
+
query_names.each do |query_name|
|
54
|
+
raise ArgumentError, "query #{query_name} is not defined" unless queries.key?(query_name)
|
55
|
+
queries[query_name].add_filter(block)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
52
59
|
# Each Report will have its own descendant of Params in order to safely add validations
|
53
60
|
def params_class
|
54
61
|
@params_class ||= Class.new(Params)
|
@@ -95,6 +102,7 @@ module Compendium
|
|
95
102
|
end
|
96
103
|
|
97
104
|
query = query_type.new(*params)
|
105
|
+
query.report = self
|
98
106
|
|
99
107
|
metrics[name] = opts[:metric] if opts.key?(:metric)
|
100
108
|
queries << query
|
data/lib/compendium/query.rb
CHANGED
@@ -7,7 +7,7 @@ require_relative '../../config/initializers/ruby/hash'
|
|
7
7
|
|
8
8
|
module Compendium
|
9
9
|
class Query
|
10
|
-
attr_reader :name, :results, :metrics
|
10
|
+
attr_reader :name, :results, :metrics, :filters
|
11
11
|
attr_accessor :options, :proc, :report
|
12
12
|
|
13
13
|
def initialize(*args)
|
@@ -17,6 +17,7 @@ module Compendium
|
|
17
17
|
|
18
18
|
@name, @options, @proc = args
|
19
19
|
@metrics = ::Collection[Metric]
|
20
|
+
@filters = ::Collection[Proc]
|
20
21
|
end
|
21
22
|
|
22
23
|
def initialize_clone(*)
|
@@ -25,22 +26,40 @@ module Compendium
|
|
25
26
|
end
|
26
27
|
|
27
28
|
def run(params, context = self)
|
28
|
-
|
29
|
-
|
29
|
+
if report.is_a?(Class)
|
30
|
+
# If running a query directly from a class rather than an instance, the class's query should
|
31
|
+
# not be affected/modified, so run the query without a reference back to the report.
|
32
|
+
# Otherwise, if the class is subsequently instantiated, the instance will already have results.
|
33
|
+
dup.tap{ |q| q.report = nil }.run(params, context)
|
34
|
+
else
|
35
|
+
collect_results(context, params)
|
36
|
+
collect_metrics(context)
|
30
37
|
|
31
|
-
|
38
|
+
@results
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Get a URL for this query (format: :json set by default)
|
43
|
+
def url(params = {})
|
44
|
+
report.url(params.merge(query: self.name))
|
32
45
|
end
|
33
46
|
|
34
47
|
def add_metric(name, proc, options = {})
|
35
48
|
Compendium::Metric.new(name, self.name, proc, options).tap { |m| @metrics << m }
|
36
49
|
end
|
37
50
|
|
51
|
+
def add_filter(filter)
|
52
|
+
@filters << filter
|
53
|
+
end
|
54
|
+
|
38
55
|
def render_table(template, *options, &block)
|
39
56
|
Compendium::Presenters::Table.new(template, self, *options, &block).render unless empty?
|
40
57
|
end
|
41
58
|
|
42
59
|
def render_chart(template, *options, &block)
|
43
|
-
|
60
|
+
# A query can be rendered regardless of if it has data or not
|
61
|
+
# Rendering a chart with no result set builds a chart scaffold which can be updated through AJAX
|
62
|
+
Compendium::Presenters::Chart.new(template, self, *options, &block).render
|
44
63
|
end
|
45
64
|
|
46
65
|
def ran?
|
@@ -55,15 +74,16 @@ module Compendium
|
|
55
74
|
|
56
75
|
# A query is empty if it has no results
|
57
76
|
def empty?
|
58
|
-
results.
|
77
|
+
results.blank?
|
59
78
|
end
|
60
79
|
|
61
80
|
private
|
62
81
|
|
63
82
|
def collect_results(context, *params)
|
64
83
|
command = context.instance_exec(*params, &proc) if proc
|
65
|
-
|
66
|
-
|
84
|
+
results = fetch_results(command)
|
85
|
+
results = filter_results(results, *params) if filters.any?
|
86
|
+
@results = ResultSet.new(results) if results
|
67
87
|
end
|
68
88
|
|
69
89
|
def collect_metrics(context)
|
@@ -74,6 +94,20 @@ module Compendium
|
|
74
94
|
(options.fetch(:collect, nil) == :active_record) ? command : execute_command(command)
|
75
95
|
end
|
76
96
|
|
97
|
+
def filter_results(results, params)
|
98
|
+
return unless results
|
99
|
+
|
100
|
+
filters.each do |f|
|
101
|
+
if f.arity == 2
|
102
|
+
results = f.call(results, params)
|
103
|
+
else
|
104
|
+
results = f.call(results)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
results
|
109
|
+
end
|
110
|
+
|
77
111
|
def execute_command(command)
|
78
112
|
return [] if command.nil?
|
79
113
|
command = command.to_sql if command.respond_to?(:to_sql)
|
data/lib/compendium/report.rb
CHANGED
@@ -11,6 +11,7 @@ module Compendium
|
|
11
11
|
extend Compendium::DSL
|
12
12
|
|
13
13
|
delegate :valid?, :errors, to: :params
|
14
|
+
delegate :name, :url, to: :class
|
14
15
|
|
15
16
|
class << self
|
16
17
|
def inherited(report)
|
@@ -27,6 +28,15 @@ module Compendium
|
|
27
28
|
}
|
28
29
|
end
|
29
30
|
|
31
|
+
def name
|
32
|
+
super.underscore.gsub(/_report$/,'').to_sym
|
33
|
+
end
|
34
|
+
|
35
|
+
# Get a URL for this report (format: :json set by default)
|
36
|
+
def url(params = {})
|
37
|
+
path_helper(params)
|
38
|
+
end
|
39
|
+
|
30
40
|
# Define predicate methods for getting the report type
|
31
41
|
# ie. r.spending? checks that r == SpendingReport
|
32
42
|
def method_missing(name, *args, &block)
|
@@ -45,6 +55,16 @@ module Compendium
|
|
45
55
|
return true if name.to_s.end_with?('?') and Compendium.reports.include?(report_class)
|
46
56
|
super
|
47
57
|
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def path_helper(params)
|
62
|
+
unless Rails.application.routes.url_helpers.method_defined? :compendium_reports_run_path
|
63
|
+
raise ActionController::RoutingError, "compendium_reports_run_path must be defined"
|
64
|
+
end
|
65
|
+
|
66
|
+
Rails.application.routes.url_helpers.compendium_reports_run_path(self.name, params.reverse_merge(format: :json))
|
67
|
+
end
|
48
68
|
end
|
49
69
|
|
50
70
|
def initialize(params = {})
|
data/lib/compendium/version.rb
CHANGED
data/spec/dsl_spec.rb
CHANGED
@@ -60,8 +60,8 @@ describe Compendium::DSL do
|
|
60
60
|
r.test.report.should == r
|
61
61
|
end
|
62
62
|
|
63
|
-
it "should
|
64
|
-
subject.test.report.should
|
63
|
+
it "should relate a query to the report class" do
|
64
|
+
subject.test.report.should == subject
|
65
65
|
end
|
66
66
|
|
67
67
|
context "when given a through option" do
|
@@ -159,6 +159,35 @@ describe Compendium::DSL do
|
|
159
159
|
end
|
160
160
|
end
|
161
161
|
|
162
|
+
describe "#filter" do
|
163
|
+
let(:filter_proc) { ->{ :filter } }
|
164
|
+
|
165
|
+
it "should add a filter to the given query" do
|
166
|
+
subject.query :test
|
167
|
+
subject.filter :test, &filter_proc
|
168
|
+
subject.queries[:test].filters.should include filter_proc
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should raise an error if there is no query of the given name" do
|
172
|
+
expect { subject.filter :test, &filter_proc }.to raise_error(ArgumentError, "query test is not defined")
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should allow multiple filters to be defined for the same query" do
|
176
|
+
subject.query :test
|
177
|
+
subject.filter :test, &filter_proc
|
178
|
+
subject.filter :test, &->{ :another_filter }
|
179
|
+
subject.queries[:test].filters.count.should == 2
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should allow a filter to be applied to multiple queries at once" do
|
183
|
+
subject.query :query1
|
184
|
+
subject.query :query2
|
185
|
+
subject.filter :query1, :query2, &filter_proc
|
186
|
+
subject.queries[:query1].filters.should include filter_proc
|
187
|
+
subject.queries[:query2].filters.should include filter_proc
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
162
191
|
it "should allow previously defined queries to be redefined by name" do
|
163
192
|
subject.query :test_query
|
164
193
|
subject.test_query foo: :bar
|
@@ -2,16 +2,16 @@ require 'spec_helper'
|
|
2
2
|
require 'compendium/presenters/chart'
|
3
3
|
|
4
4
|
describe Compendium::Presenters::Chart do
|
5
|
+
let(:template) { double('Template', forgery_protection_strategy: nil, request_forgery_protection_token: :authenticity_token, form_authenticity_token: "ABCDEFGHIJ").as_null_object }
|
6
|
+
let(:query) { double('Query', name: 'test_query', results: results, ran?: true, options: {}).as_null_object }
|
7
|
+
let(:results) { Compendium::ResultSet.new([]) }
|
8
|
+
|
5
9
|
before do
|
6
10
|
described_class.any_instance.stub(:provider) { double('ChartProvider') }
|
7
11
|
described_class.any_instance.stub(:initialize_chart_provider)
|
8
12
|
end
|
9
13
|
|
10
14
|
describe '#initialize' do
|
11
|
-
let(:template) { double('Template') }
|
12
|
-
let(:query) { double('Query', name: 'test_query', results: results, options: {}) }
|
13
|
-
let(:results) { Compendium::ResultSet.new([]) }
|
14
|
-
|
15
15
|
context 'when all params are given' do
|
16
16
|
subject{ described_class.new(template, query, :pie, :container) }
|
17
17
|
|
@@ -33,5 +33,39 @@ describe Compendium::Presenters::Chart do
|
|
33
33
|
its(:data) { should == results.records[:one] }
|
34
34
|
its(:container) { should == 'test_query' }
|
35
35
|
end
|
36
|
+
|
37
|
+
context "when the query has not been run" do
|
38
|
+
before { query.stub(ran?: false, url: '/path/to/query.json') }
|
39
|
+
|
40
|
+
subject{ described_class.new(template, query, :pie, params: { foo: 'bar' }) }
|
41
|
+
|
42
|
+
its(:data) { should == '/path/to/query.json' }
|
43
|
+
its(:params) { should == { report: { foo: 'bar' } } }
|
44
|
+
|
45
|
+
context "when CSRF protection is enabled" do
|
46
|
+
before { template.stub(forgery_protection_strategy: double('CSRF')) }
|
47
|
+
|
48
|
+
its(:params) { should include authenticity_token: "ABCDEFGHIJ" }
|
49
|
+
end
|
50
|
+
|
51
|
+
context "when CSRF protection is disabled" do
|
52
|
+
its(:params) { should_not include authenticity_token: "ABCDEFGHIJ" }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#remote?' do
|
58
|
+
it 'should be true if options[:remote] is set to true' do
|
59
|
+
described_class.new(template, query, :pie, remote: true).should be_remote
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should be true if the query has not been run yet' do
|
63
|
+
query.stub(run?: false)
|
64
|
+
described_class.new(template, query, :pie).should_be_remote
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should be false otherwise' do
|
68
|
+
described_class.new(template, query, :pie).should_not be_remote
|
69
|
+
end
|
36
70
|
end
|
37
71
|
end
|
data/spec/query_spec.rb
CHANGED
@@ -49,6 +49,43 @@ describe Compendium::Query do
|
|
49
49
|
query = described_class.new(:blank, {}, nil)
|
50
50
|
query.run(nil).should be_empty
|
51
51
|
end
|
52
|
+
|
53
|
+
it "should filter the result set if a filter is provided" do
|
54
|
+
query.add_filter(-> data { data.reject(&:odd?) })
|
55
|
+
query.run(nil).should == [2]
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should run multiple filters if given" do
|
59
|
+
query.add_filter(-> data { data.reject(&:odd?) })
|
60
|
+
query.add_filter(-> data { data.reject(&:even?) })
|
61
|
+
query.run(nil).should == []
|
62
|
+
end
|
63
|
+
|
64
|
+
context "when the query belongs to a report class" do
|
65
|
+
let(:report) do
|
66
|
+
Class.new(Compendium::Report) do
|
67
|
+
query(:test) { [1, 2, 3] }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
subject { report.queries[:test] }
|
72
|
+
|
73
|
+
before { described_class.any_instance.stub(:fetch_results) { |c| c } }
|
74
|
+
|
75
|
+
it "should return its results" do
|
76
|
+
subject.run(nil).should == [1, 2, 3]
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should not affect the report" do
|
80
|
+
subject.run(nil)
|
81
|
+
report.queries[:test].results.should be_nil
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should not affect future instances of the report" do
|
85
|
+
subject.run(nil)
|
86
|
+
report.new.queries[:test].results.should be_nil
|
87
|
+
end
|
88
|
+
end
|
52
89
|
end
|
53
90
|
|
54
91
|
describe "#nil?" do
|
@@ -65,9 +102,10 @@ describe Compendium::Query do
|
|
65
102
|
let(:template) { double("Template") }
|
66
103
|
subject { described_class.new(:test, {}, -> * {}) }
|
67
104
|
|
68
|
-
it "should
|
105
|
+
it "should initialize a new Chart presenter if the query has no results" do
|
69
106
|
subject.stub(empty?: true)
|
70
|
-
|
107
|
+
Compendium::Presenters::Chart.should_receive(:new).with(template, subject).and_return(double("Presenter").as_null_object)
|
108
|
+
subject.render_chart(template)
|
71
109
|
end
|
72
110
|
|
73
111
|
it "should initialize a new Chart presenter if the query has results" do
|
@@ -92,4 +130,15 @@ describe Compendium::Query do
|
|
92
130
|
subject.render_table(template)
|
93
131
|
end
|
94
132
|
end
|
133
|
+
|
134
|
+
describe "#url" do
|
135
|
+
let(:report) { double("Report") }
|
136
|
+
subject { described_class.new(:test, {}, ->{}) }
|
137
|
+
before { subject.report = report }
|
138
|
+
|
139
|
+
it "should build a URL using its report's URL" do
|
140
|
+
report.should_receive(:url).with(query: :test)
|
141
|
+
subject.url
|
142
|
+
end
|
143
|
+
end
|
95
144
|
end
|
data/spec/report_spec.rb
CHANGED
@@ -28,6 +28,11 @@ describe Compendium::Report do
|
|
28
28
|
its(:metrics) { should_not equal report2.metrics }
|
29
29
|
end
|
30
30
|
|
31
|
+
describe ".name" do
|
32
|
+
subject { TestReport = Class.new(described_class) }
|
33
|
+
its(:name) { should == :test }
|
34
|
+
end
|
35
|
+
|
31
36
|
describe "#run" do
|
32
37
|
context do
|
33
38
|
let(:report_class) do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: compendium
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Vandersluis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-04-
|
11
|
+
date: 2014-04-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
type: :runtime
|
@@ -102,6 +102,7 @@ extensions: []
|
|
102
102
|
extra_rdoc_files: []
|
103
103
|
files:
|
104
104
|
- .gitignore
|
105
|
+
- CHANGELOG.md
|
105
106
|
- Gemfile
|
106
107
|
- LICENSE.txt
|
107
108
|
- README.md
|
@@ -129,7 +130,6 @@ files:
|
|
129
130
|
- config/locales/en.yml
|
130
131
|
- lib/compendium.rb
|
131
132
|
- lib/compendium/abstract_chart_provider.rb
|
132
|
-
- lib/compendium/chart_provider/amcharts.rb
|
133
133
|
- lib/compendium/collection_query.rb
|
134
134
|
- lib/compendium/context_wrapper.rb
|
135
135
|
- lib/compendium/dsl.rb
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Compendium
|
2
|
-
module ChartProvider
|
3
|
-
# Uses the amcharts.rb gem to provide charting
|
4
|
-
class AmCharts < Compendium::AbstractChartProvider
|
5
|
-
def initialize(type, data, &setup_proc)
|
6
|
-
@chart = chart_class(type).new(data, &setup_proc)
|
7
|
-
end
|
8
|
-
|
9
|
-
def render(template, container)
|
10
|
-
template.amchart(chart, container)
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
def chart_class(type)
|
16
|
-
::AmCharts::Chart.const_get(type.to_s.titlecase)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|