compendium 1.0.2 → 1.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.
- checksums.yaml +8 -8
- data/app/classes/compendium/presenters/chart.rb +10 -3
- data/app/classes/compendium/presenters/option.rb +5 -3
- data/app/classes/compendium/presenters/query.rb +2 -0
- data/app/controllers/compendium/reports_controller.rb +9 -3
- data/app/views/compendium/reports/setup.haml +1 -1
- data/compendium.gemspec +1 -1
- data/lib/compendium/collection_query.rb +44 -0
- data/lib/compendium/dsl.rb +33 -12
- data/lib/compendium/param_types.rb +1 -1
- data/lib/compendium/params.rb +10 -3
- data/lib/compendium/query.rb +19 -39
- data/lib/compendium/report.rb +38 -3
- data/lib/compendium/result_set.rb +4 -1
- data/lib/compendium/through_query.rb +43 -0
- data/lib/compendium/version.rb +1 -1
- data/lib/compendium.rb +2 -0
- data/spec/collection_query_spec.rb +46 -0
- data/spec/dsl_spec.rb +69 -1
- data/spec/params_spec.rb +22 -7
- data/spec/presenters/chart_spec.rb +37 -0
- data/spec/presenters/option_spec.rb +1 -1
- data/spec/query_spec.rb +32 -34
- data/spec/report_spec.rb +56 -0
- data/spec/result_set_spec.rb +23 -0
- data/spec/through_query_spec.rb +71 -0
- metadata +14 -4
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ODBjOTg1ZGM3NjVhYTM3ZjcxZDM5YjMyYjI1M2I2MzJjYTkzZmFiNg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
Yzg1ZDk0MmUxYTlkMDg2NTgzYTIxMzEyZjk3NjcxYjYwMzc2ZjhiZQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZTA4YTdjYjUwOWE5ZTU3ODVhZmRhMzU2NjViZjZiMGFjZjk3ZDhkYjY0MjIz
|
10
|
+
NjY3ZmVjODkzNGYyNWNiNDY2ODlmZWNiNTI4NGI2MGFhNGIzNThjMzgwZjZl
|
11
|
+
ZTM5MzIzNjVlNDdmY2FiN2U2MTAxZTQwN2Q0NWUxZmFmN2Q2MjM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
N2QyNWI2OGU4ZGQ0OWJiODMxZDNhOTA4NDU1NTliOTViNzAxMzQ3MGRlZTAz
|
14
|
+
Y2UxODhjMjUyZTEzNjFhYmI5MzkwZGI3ZTYzNzEwMWM4NWVmNGVlZjJmYjdh
|
15
|
+
NTZkYWJkODVmYzk4OTUzZTVhNjkxNDVjODhjN2QyNmY2N2Q4ZTM=
|
@@ -1,11 +1,18 @@
|
|
1
|
+
require 'compendium/presenters/query'
|
2
|
+
require 'active_support/core_ext/array/extract_options'
|
3
|
+
|
1
4
|
module Compendium::Presenters
|
2
5
|
class Chart < Query
|
3
|
-
attr_reader :data, :chart_provider
|
6
|
+
attr_reader :data, :container, :chart_provider
|
7
|
+
|
8
|
+
def initialize(template, object, *args, &setup)
|
9
|
+
options = args.extract_options!
|
10
|
+
type, container = args
|
4
11
|
|
5
|
-
def initialize(template, object, type, container = nil, &setup)
|
6
12
|
super(template, object)
|
7
13
|
|
8
|
-
@data = results.records
|
14
|
+
@data = options[:index] ? results.records[options[:index]] : results
|
15
|
+
@data = @data.records if @data.is_a?(Compendium::ResultSet)
|
9
16
|
@data = @data[0...-1] if query.options[:totals]
|
10
17
|
|
11
18
|
@container = container || query.name
|
@@ -5,7 +5,7 @@ module Compendium::Presenters
|
|
5
5
|
presents :option
|
6
6
|
|
7
7
|
def name
|
8
|
-
t(option.name)
|
8
|
+
t("options.#{option.name}", cascade: { offset: 2 })
|
9
9
|
end
|
10
10
|
|
11
11
|
def label(form)
|
@@ -21,10 +21,12 @@ module Compendium::Presenters
|
|
21
21
|
out << content_tag(:span, label, class: 'option-label')
|
22
22
|
|
23
23
|
if option.note?
|
24
|
-
|
24
|
+
key = option.note == true ? :"#{option.name}_note" : option.note
|
25
|
+
note = t("options.#{key}", cascade: { offset: 2 })
|
26
|
+
title = t("options.#{option.name}_note_title", default: '', cascade: { offset: 2 })
|
25
27
|
|
26
28
|
if defined?(AccessibleTooltip)
|
27
|
-
return accessible_tooltip(:help, label: out, title:
|
29
|
+
return accessible_tooltip(:help, label: out, title: title) { note }
|
28
30
|
else
|
29
31
|
out << content_tag(:div, note, class: 'option-note')
|
30
32
|
end
|
@@ -4,6 +4,7 @@ module Compendium
|
|
4
4
|
include Compendium::ReportsHelper
|
5
5
|
|
6
6
|
before_filter :find_report
|
7
|
+
before_filter :validate_options, only: :run
|
7
8
|
before_filter :run_report, only: :run
|
8
9
|
|
9
10
|
def setup
|
@@ -24,6 +25,7 @@ module Compendium
|
|
24
25
|
begin
|
25
26
|
require(@report_name) unless Rails.env.development? or Module.const_defined?(@report_name.classify)
|
26
27
|
@report_class = @report_name.camelize.constantize
|
28
|
+
@report = setup_report
|
27
29
|
rescue LoadError
|
28
30
|
flash[:error] = t(:invalid_report)
|
29
31
|
redirect_to action: :index
|
@@ -31,16 +33,20 @@ module Compendium
|
|
31
33
|
end
|
32
34
|
|
33
35
|
def render_setup(opts = {})
|
34
|
-
locals = { report:
|
35
|
-
render_if_exists(opts.merge(locals: locals)) || render(locals: locals)
|
36
|
+
locals = { report: @report, prefix: @prefix }
|
37
|
+
opts.empty? ? render(action: :setup, locals: locals) : render_if_exists(opts.merge(locals: locals)) || render(action: :setup, locals: locals)
|
36
38
|
end
|
37
39
|
|
38
40
|
def setup_report
|
39
41
|
@report_class.new(params[:report] || {})
|
40
42
|
end
|
41
43
|
|
44
|
+
def validate_options
|
45
|
+
render_setup and return unless @report.valid?
|
46
|
+
end
|
47
|
+
|
42
48
|
def run_report
|
43
|
-
@report
|
49
|
+
@report.run(self)
|
44
50
|
end
|
45
51
|
|
46
52
|
def get_template_prefixes
|
data/compendium.gemspec
CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |gem|
|
|
21
21
|
gem.add_dependency 'rails', '>= 3.0.0'
|
22
22
|
gem.add_dependency 'sass-rails', '>= 3.0.0'
|
23
23
|
gem.add_dependency 'compass-rails', '>= 1.0.0'
|
24
|
-
gem.add_dependency 'collection_of', '1.0.
|
24
|
+
gem.add_dependency 'collection_of', '1.0.5'
|
25
25
|
gem.add_dependency 'inheritable_attr', '>= 1.0.0'
|
26
26
|
gem.add_development_dependency 'rspec', '~> 2.0'
|
27
27
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'compendium/query'
|
2
|
+
|
3
|
+
module Compendium
|
4
|
+
# A CollectionQuery is a Query which runs once for each in a given set of criteria
|
5
|
+
class CollectionQuery < Query
|
6
|
+
attr_accessor :collection
|
7
|
+
|
8
|
+
def initialize(*)
|
9
|
+
super
|
10
|
+
self.collection = prepare_collection(@options[:collection])
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(params, context = self)
|
14
|
+
collection_values = get_collection_values(context, params)
|
15
|
+
|
16
|
+
results = collection_values.inject({}) do |r, (key, value)|
|
17
|
+
res = collect_results(context, params, key, value)
|
18
|
+
r[key] = res unless res.empty?
|
19
|
+
r
|
20
|
+
end
|
21
|
+
|
22
|
+
# A CollectionQuery's results will be a ResultSet of ResultSets
|
23
|
+
@results = ResultSet.new(results)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def get_collection_values(context, params)
|
29
|
+
self.collection = get_associated_query(collection) if collection.is_a?(Symbol)
|
30
|
+
|
31
|
+
if collection.is_a?(Query)
|
32
|
+
collection.run(params, context) unless collection.ran?
|
33
|
+
collection.results
|
34
|
+
else
|
35
|
+
collection
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def prepare_collection(collection)
|
40
|
+
return collection if collection.is_a?(Query) or collection.is_a?(Symbol)
|
41
|
+
collection.is_a?(Hash) ? collection : Hash[collection.zip(collection)]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/compendium/dsl.rb
CHANGED
@@ -7,7 +7,7 @@ module Compendium
|
|
7
7
|
module DSL
|
8
8
|
def self.extended(klass)
|
9
9
|
klass.inheritable_attr :queries, default: ::Collection[Query]
|
10
|
-
klass.inheritable_attr :options, default:
|
10
|
+
klass.inheritable_attr :options, default: ::Collection[Option]
|
11
11
|
end
|
12
12
|
|
13
13
|
def query(name, opts = {}, &block)
|
@@ -20,16 +20,20 @@ module Compendium
|
|
20
20
|
opts = args.extract_options!
|
21
21
|
type = args.shift
|
22
22
|
|
23
|
+
add_params_validations(name, opts.delete(:validates))
|
24
|
+
|
23
25
|
if options[name]
|
24
26
|
options[name].type = type if type
|
25
27
|
options[name].default = opts.delete(:default) if opts.key?(:default)
|
26
28
|
options[name].merge!(opts)
|
27
29
|
else
|
28
|
-
options
|
30
|
+
options << Compendium::Option.new(opts.merge(name: name, type: type))
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
32
|
-
def metric(name,
|
34
|
+
def metric(name, *args, &block)
|
35
|
+
proc = args.first.is_a?(Proc) ? args.first : block
|
36
|
+
opts = args.extract_options!
|
33
37
|
raise ArgumentError, 'through option must be specified for metric' unless opts.key?(:through)
|
34
38
|
|
35
39
|
[opts.delete(:through)].flatten.each do |query|
|
@@ -38,6 +42,15 @@ module Compendium
|
|
38
42
|
end
|
39
43
|
end
|
40
44
|
|
45
|
+
# Each Report will have its own descendant of Params in order to safely add validations
|
46
|
+
def params_class
|
47
|
+
@params_class ||= Class.new(Params)
|
48
|
+
end
|
49
|
+
|
50
|
+
def params_class=(klass)
|
51
|
+
@params_class = klass
|
52
|
+
end
|
53
|
+
|
41
54
|
# Allow defined queries to be redefined by name, eg:
|
42
55
|
# query :main_query
|
43
56
|
# main_query { collect_records_here }
|
@@ -59,22 +72,30 @@ module Compendium
|
|
59
72
|
|
60
73
|
private
|
61
74
|
|
62
|
-
def define_query(name, opts,
|
63
|
-
|
64
|
-
|
75
|
+
def define_query(name, opts, &block)
|
76
|
+
params = [name.to_sym, opts, block]
|
77
|
+
query_type = Query
|
65
78
|
|
66
|
-
if opts.key?(:
|
79
|
+
if opts.key?(:collection)
|
80
|
+
query_type = CollectionQuery
|
81
|
+
elsif opts.key?(:through)
|
82
|
+
# Ensure each through query is defined
|
67
83
|
through = [opts[:through]].flatten
|
84
|
+
through.each { |q| raise ArgumentError, "query #{q} is not defined" unless self.queries.include?(q.to_sym) }
|
68
85
|
|
69
|
-
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
query.through = through
|
86
|
+
query_type = ThroughQuery
|
87
|
+
params.insert(1, through)
|
74
88
|
end
|
75
89
|
|
90
|
+
query = query_type.new(*params)
|
91
|
+
|
76
92
|
metrics[name] = opts[:metric] if opts.key?(:metric)
|
77
93
|
queries << query
|
78
94
|
end
|
95
|
+
|
96
|
+
def add_params_validations(name, validations)
|
97
|
+
return if validations.blank?
|
98
|
+
self.params_class.validates name, validations
|
99
|
+
end
|
79
100
|
end
|
80
101
|
end
|
data/lib/compendium/params.rb
CHANGED
@@ -2,9 +2,12 @@ require 'compendium/open_hash'
|
|
2
2
|
require 'compendium/param_types'
|
3
3
|
require 'active_support/core_ext/string/inflections'
|
4
4
|
require 'active_support/core_ext/object/blank'
|
5
|
+
require 'active_model'
|
5
6
|
|
6
7
|
module Compendium
|
7
8
|
class Params < OpenHash
|
9
|
+
include ActiveModel::Validations
|
10
|
+
|
8
11
|
attr_reader :options
|
9
12
|
|
10
13
|
def initialize(hash = {}, options = {})
|
@@ -12,15 +15,19 @@ module Compendium
|
|
12
15
|
super(prepare_hash_from_options(hash))
|
13
16
|
end
|
14
17
|
|
18
|
+
def self.model_name
|
19
|
+
ActiveModel::Name.new(Compendium::Params, Compendium, 'compendium.params')
|
20
|
+
end
|
21
|
+
|
15
22
|
protected
|
16
23
|
|
17
24
|
def prepare_hash_from_options(params)
|
18
25
|
params = params.slice(*options.keys)
|
19
26
|
|
20
|
-
options.each do |
|
27
|
+
options.each do |option|
|
21
28
|
begin
|
22
|
-
klass = "Compendium::#{"#{
|
23
|
-
params[
|
29
|
+
klass = "Compendium::#{"#{option.type}Param".classify}".constantize
|
30
|
+
params[option.name] = klass.new(get_default_value(params[option.name], option.default), option.choices)
|
24
31
|
rescue IndexError
|
25
32
|
raise IndexError, "invalid index for #{option_name}"
|
26
33
|
end
|
data/lib/compendium/query.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
require 'compendium/result_set'
|
2
2
|
require 'compendium/params'
|
3
|
+
require 'compendium/presenters/chart'
|
4
|
+
require 'compendium/presenters/table'
|
3
5
|
require 'collection_of'
|
4
6
|
require_relative '../../config/initializers/ruby/hash'
|
5
7
|
|
6
8
|
module Compendium
|
7
9
|
class Query
|
8
10
|
attr_reader :name, :results, :metrics
|
9
|
-
attr_accessor :options, :proc, :
|
11
|
+
attr_accessor :options, :proc, :report
|
10
12
|
|
11
13
|
def initialize(*args)
|
12
14
|
@report = args.shift if arg_is_report?(args.first)
|
@@ -23,7 +25,7 @@ module Compendium
|
|
23
25
|
end
|
24
26
|
|
25
27
|
def run(params, context = self)
|
26
|
-
collect_results(
|
28
|
+
collect_results(context, params)
|
27
29
|
collect_metrics(context)
|
28
30
|
|
29
31
|
@results
|
@@ -34,11 +36,11 @@ module Compendium
|
|
34
36
|
end
|
35
37
|
|
36
38
|
def render_table(template, *options, &block)
|
37
|
-
Compendium::Presenters::Table.new(template, self, *options, &block).render
|
39
|
+
Compendium::Presenters::Table.new(template, self, *options, &block).render unless empty?
|
38
40
|
end
|
39
41
|
|
40
42
|
def render_chart(template, *options, &block)
|
41
|
-
Compendium::Presenters::Chart.new(template, self, *options, &block).render
|
43
|
+
Compendium::Presenters::Chart.new(template, self, *options, &block).render unless empty?
|
42
44
|
end
|
43
45
|
|
44
46
|
def ran?
|
@@ -46,24 +48,20 @@ module Compendium
|
|
46
48
|
end
|
47
49
|
alias_method :has_run?, :ran?
|
48
50
|
|
51
|
+
# A query is nil if it has no proc
|
49
52
|
def nil?
|
50
53
|
proc.nil?
|
51
54
|
end
|
52
55
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
args = params
|
58
|
-
else
|
59
|
-
args = collect_through_query_results(through, params, context)
|
56
|
+
# A query is empty if it has no results
|
57
|
+
def empty?
|
58
|
+
results.empty?
|
59
|
+
end
|
60
60
|
|
61
|
-
|
62
|
-
# depends on the results of its parents.
|
63
|
-
return @results = ResultSet.new([]) if args.compact.empty?
|
64
|
-
end
|
61
|
+
private
|
65
62
|
|
66
|
-
|
63
|
+
def collect_results(context, *params)
|
64
|
+
command = context.instance_exec(*params, &proc) if proc
|
67
65
|
command = fetch_results(command)
|
68
66
|
@results = ResultSet.new(command) if command
|
69
67
|
end
|
@@ -73,11 +71,7 @@ module Compendium
|
|
73
71
|
end
|
74
72
|
|
75
73
|
def fetch_results(command)
|
76
|
-
|
77
|
-
command
|
78
|
-
else
|
79
|
-
execute_command(command)
|
80
|
-
end
|
74
|
+
(options.fetch(:collect, nil) == :active_record) ? command : execute_command(command)
|
81
75
|
end
|
82
76
|
|
83
77
|
def execute_command(command)
|
@@ -90,26 +84,12 @@ module Compendium
|
|
90
84
|
::ActiveRecord::Base.connection.select_all(command)
|
91
85
|
end
|
92
86
|
|
93
|
-
def collect_through_query_results(through, params, context)
|
94
|
-
results = {}
|
95
|
-
|
96
|
-
through = [through].flatten.map(&method(:get_through_query))
|
97
|
-
|
98
|
-
through.each do |q|
|
99
|
-
q.run(params, context) unless q.ran?
|
100
|
-
results[q.name] = q.results.records
|
101
|
-
end
|
102
|
-
|
103
|
-
results = results[through.first.name] if through.size == 1
|
104
|
-
results
|
105
|
-
end
|
106
|
-
|
107
|
-
def get_through_query(name)
|
108
|
-
report.queries[name]
|
109
|
-
end
|
110
|
-
|
111
87
|
def arg_is_report?(arg)
|
112
88
|
arg.is_a?(Report) or (arg.is_a?(Class) and arg < Report)
|
113
89
|
end
|
90
|
+
|
91
|
+
def get_associated_query(query)
|
92
|
+
query.is_a?(Query) ? query : report.queries[query]
|
93
|
+
end
|
114
94
|
end
|
115
95
|
end
|
data/lib/compendium/report.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'active_support/core_ext/class/attribute_accessors'
|
2
2
|
require 'active_support/core_ext/hash/slice'
|
3
|
+
require 'active_support/core_ext/module/delegation'
|
4
|
+
require 'active_support/core_ext/string/inflections'
|
3
5
|
require 'compendium/dsl'
|
4
6
|
|
5
7
|
module Compendium
|
@@ -8,12 +10,45 @@ module Compendium
|
|
8
10
|
|
9
11
|
extend Compendium::DSL
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
+
delegate :valid?, :errors, to: :params
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def inherited(report)
|
17
|
+
Compendium.reports << report
|
18
|
+
|
19
|
+
# Each Report object has its own Params class so that validations can be added without affecting other
|
20
|
+
# reports. However, validations also need to be inherited, so when inheriting a report, subclass its
|
21
|
+
# params_class
|
22
|
+
report.params_class = Class.new(self.params_class)
|
23
|
+
report.params_class.class_eval %Q{
|
24
|
+
def self.model_name
|
25
|
+
ActiveModel::Name.new(Compendium::Params, Compendium, "compendium.params.#{report.name.underscore rescue 'report'}")
|
26
|
+
end
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
# Define predicate methods for getting the report type
|
31
|
+
# ie. r.spending? checks that r == SpendingReport
|
32
|
+
def method_missing(name, *args, &block)
|
33
|
+
prefix = name.to_s.gsub(/[?!]\z/, '')
|
34
|
+
report_class = "#{prefix}_report".classify.constantize rescue nil
|
35
|
+
|
36
|
+
return self == report_class if name.to_s.end_with?('?') and Compendium.reports.include?(report_class)
|
37
|
+
|
38
|
+
super
|
39
|
+
end
|
40
|
+
|
41
|
+
def respond_to_missing?(name, include_private = false)
|
42
|
+
prefix = name.to_s.gsub(/[?!]\z/, '')
|
43
|
+
report_class = "#{prefix}_report".classify.constantize rescue nil
|
44
|
+
|
45
|
+
return true if name.to_s.end_with?('?') and Compendium.reports.include?(report_class)
|
46
|
+
super
|
47
|
+
end
|
13
48
|
end
|
14
49
|
|
15
50
|
def initialize(params = {})
|
16
|
-
@params =
|
51
|
+
@params = self.class.params_class.new(params, options)
|
17
52
|
|
18
53
|
# When creating a new report, map each query back to the report
|
19
54
|
queries.each { |q| q.report = self }
|
@@ -1,8 +1,9 @@
|
|
1
1
|
require 'active_support/core_ext/module/delegation'
|
2
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
2
3
|
|
3
4
|
module Compendium
|
4
5
|
class ResultSet
|
5
|
-
delegate :first, :last, :to_a, :empty?, :each, :map, :[], :count, :length, :size, :==, to: :records
|
6
|
+
delegate :first, :last, :to_a, :empty?, :each, :map, :inject, :select, :detect, :[], :count, :length, :size, :==, to: :records
|
6
7
|
|
7
8
|
attr_reader :records
|
8
9
|
alias :all :records
|
@@ -11,6 +12,8 @@ module Compendium
|
|
11
12
|
@records = records.map do |r|
|
12
13
|
r.respond_to?(:with_indifferent_access) ? r.with_indifferent_access : r
|
13
14
|
end
|
15
|
+
|
16
|
+
@records = Hash[@records] if records.is_a?(Hash)
|
14
17
|
end
|
15
18
|
|
16
19
|
def keys
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'compendium/query'
|
2
|
+
|
3
|
+
module Compendium
|
4
|
+
class ThroughQuery < Query
|
5
|
+
attr_accessor :through
|
6
|
+
|
7
|
+
def initialize(*args)
|
8
|
+
@report = args.shift if arg_is_report?(args.first)
|
9
|
+
@through = args.slice!(1)
|
10
|
+
super(*args)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def collect_results(context, params)
|
16
|
+
args = collect_through_query_results(params, context)
|
17
|
+
|
18
|
+
# If none of the through queries have any results, we shouldn't try to execute the query, because it
|
19
|
+
# depends on the results of its parents.
|
20
|
+
return @results = ResultSet.new([]) if args.compact.empty?
|
21
|
+
|
22
|
+
super(context, args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def fetch_results(command)
|
26
|
+
command
|
27
|
+
end
|
28
|
+
|
29
|
+
def collect_through_query_results(params, context)
|
30
|
+
results = {}
|
31
|
+
|
32
|
+
queries = [through].flatten.map(&method(:get_associated_query))
|
33
|
+
|
34
|
+
queries.each do |q|
|
35
|
+
q.run(params, context) unless q.ran?
|
36
|
+
results[q.name] = q.results.records
|
37
|
+
end
|
38
|
+
|
39
|
+
results = results[queries.first.name] if queries.size == 1
|
40
|
+
results
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/compendium/version.rb
CHANGED
data/lib/compendium.rb
CHANGED
@@ -5,6 +5,7 @@ require 'active_support/configurable'
|
|
5
5
|
module Compendium
|
6
6
|
autoload :AbstractChartProvider, 'compendium/abstract_chart_provider'
|
7
7
|
autoload :ChartProvider, 'compendium/abstract_chart_provider'
|
8
|
+
autoload :CollectionQuery, 'compendium/collection_query'
|
8
9
|
autoload :ContextWrapper, 'compendium/context_wrapper'
|
9
10
|
autoload :DSL, 'compendium/dsl'
|
10
11
|
autoload :Metric, 'compendium/metric'
|
@@ -13,6 +14,7 @@ module Compendium
|
|
13
14
|
autoload :Query, 'compendium/query'
|
14
15
|
autoload :ResultSet, 'compendium/result_set'
|
15
16
|
autoload :Report, 'compendium/report'
|
17
|
+
autoload :ThroughQuery, 'compendium/through_query'
|
16
18
|
|
17
19
|
autoload :Param, 'compendium/param_types'
|
18
20
|
autoload :BooleanParam, 'compendium/param_types'
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'compendium/collection_query'
|
3
|
+
|
4
|
+
describe Compendium::CollectionQuery do
|
5
|
+
let(:collection) { { one: 1, two: 2, three: 3 } }
|
6
|
+
subject { described_class.new(:collection_query, { collection: collection }, -> _, key, item { [item * 2] }) }
|
7
|
+
|
8
|
+
before { Compendium::Query.any_instance.stub(:execute_query) { |cmd| cmd } }
|
9
|
+
|
10
|
+
describe "#run" do
|
11
|
+
context do
|
12
|
+
before { subject.run(nil) }
|
13
|
+
|
14
|
+
its(:results) { should be_a Compendium::ResultSet }
|
15
|
+
its(:results) { should == { one: [2], two: [4], three: [6] } }
|
16
|
+
|
17
|
+
context "when given an array instead of a hash" do
|
18
|
+
let(:collection) { [1, 2, 3] }
|
19
|
+
|
20
|
+
its(:results) { should be_a Compendium::ResultSet }
|
21
|
+
its(:results) { should == { 1 => [2], 2 => [4], 3 => [6] } }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should not collect empty results" do
|
26
|
+
subject.proc = -> _, key, item { [item] if item > 2 }
|
27
|
+
subject.run(nil)
|
28
|
+
subject.results.should == { three: [3] }
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when given another query" do
|
32
|
+
let(:q) { Compendium::Query.new(:q, {}, -> * { { one: 1, two: 2, three: 3 } }) }
|
33
|
+
subject { described_class.new(:collection, { collection: q }, -> _, key, item { [ item * 2 ] }) }
|
34
|
+
|
35
|
+
before { subject.run(nil) if example.metadata.fetch(:run_query, true) }
|
36
|
+
|
37
|
+
its(:results) { should == { one: [2], two: [4], three: [6] } }
|
38
|
+
|
39
|
+
it "should not re-run the query if it has already ran", run_query: false do
|
40
|
+
q.run(nil)
|
41
|
+
q.should_not_receive(:run)
|
42
|
+
subject.run(nil)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/spec/dsl_spec.rb
CHANGED
@@ -25,15 +25,34 @@ describe Compendium::DSL do
|
|
25
25
|
subject.option :starting_on, :date, default: proc
|
26
26
|
subject.options[:starting_on].default.should == proc
|
27
27
|
end
|
28
|
+
|
29
|
+
it "should add validations" do
|
30
|
+
subject.option :foo, validates: { presence: true }
|
31
|
+
subject.params_class.validators_on(:foo).should_not be_empty
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should not add validations if no validates option is given" do
|
35
|
+
subject.params_class.should_not_receive :validates
|
36
|
+
subject.option :foo
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should not bleed overridden options into the superclass" do
|
40
|
+
r = Class.new(subject)
|
41
|
+
r.option :starting_on, :boolean
|
42
|
+
r.option :new, :date
|
43
|
+
subject.options[:starting_on].should be_date
|
44
|
+
end
|
28
45
|
end
|
29
46
|
|
30
47
|
describe "#query" do
|
31
|
-
|
48
|
+
let(:report_class) do
|
32
49
|
Class.new(Compendium::Report) do
|
33
50
|
query :test
|
34
51
|
end
|
35
52
|
end
|
36
53
|
|
54
|
+
subject { report_class }
|
55
|
+
|
37
56
|
its(:queries) { should include :test }
|
38
57
|
|
39
58
|
it "should relate the new query back to the report instance" do
|
@@ -44,6 +63,42 @@ describe Compendium::DSL do
|
|
44
63
|
it "should not relate a query to the report class" do
|
45
64
|
subject.test.report.should be_nil
|
46
65
|
end
|
66
|
+
|
67
|
+
context "when given a through option" do
|
68
|
+
before { report_class.query :through, through: :test }
|
69
|
+
subject { report_class.queries[:through] }
|
70
|
+
|
71
|
+
it { should be_a Compendium::ThroughQuery }
|
72
|
+
its(:through) { should == [:test] }
|
73
|
+
end
|
74
|
+
|
75
|
+
context "when given a collection option" do
|
76
|
+
subject { report_class.queries[:collection] }
|
77
|
+
|
78
|
+
context "that is an enumerable" do
|
79
|
+
before { report_class.query :collection, collection: [] }
|
80
|
+
|
81
|
+
it { should be_a Compendium::CollectionQuery }
|
82
|
+
end
|
83
|
+
|
84
|
+
context "that is a symbol" do
|
85
|
+
let(:query) { double("Query") }
|
86
|
+
|
87
|
+
before do
|
88
|
+
Compendium::Query.any_instance.stub(:get_associated_query).with(:query).and_return(query)
|
89
|
+
report_class.query :collection, collection: :query
|
90
|
+
end
|
91
|
+
|
92
|
+
its(:collection) { should == :query }
|
93
|
+
end
|
94
|
+
|
95
|
+
context "that is a query" do
|
96
|
+
let(:query) { Compendium::Query.new(:query, {}, ->{}) }
|
97
|
+
before { report_class.query :collection, collection: query }
|
98
|
+
|
99
|
+
its(:collection) { should == query }
|
100
|
+
end
|
101
|
+
end
|
47
102
|
end
|
48
103
|
|
49
104
|
describe "#chart" do
|
@@ -81,6 +136,19 @@ describe Compendium::DSL do
|
|
81
136
|
it "should raise an error if specified for an invalid query" do
|
82
137
|
expect{ subject.metric :test_metric, metric_proc, through: :fake }.to raise_error ArgumentError, 'query fake is not defined'
|
83
138
|
end
|
139
|
+
|
140
|
+
it "should allow metrics to be defined with a block" do
|
141
|
+
subject.metric :block_metric, through: :test do
|
142
|
+
123
|
143
|
+
end
|
144
|
+
|
145
|
+
subject.queries[:test].metrics[:block_metric].run(self, nil).should == 123
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should allow metrics to be defined with a lambda" do
|
149
|
+
subject.metric :block_metric, -> * { 123 }, through: :test
|
150
|
+
subject.queries[:test].metrics[:block_metric].run(self, nil).should == 123
|
151
|
+
end
|
84
152
|
end
|
85
153
|
|
86
154
|
it "should allow previously defined queries to be redefined by name" do
|
data/spec/params_spec.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
require 'compendium/params'
|
2
2
|
|
3
3
|
describe Compendium::Params do
|
4
|
-
let(:options) {
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
let(:options) {
|
5
|
+
opts = Collection[Compendium::Option]
|
6
|
+
opts << Compendium::Option.new(name: :starting_on, type: :date, default: ->{ Date.today })
|
7
|
+
opts << Compendium::Option.new(name: :ending_on, type: :date)
|
8
|
+
opts << Compendium::Option.new(name: :report_type, type: :radio, choices: [:big, :small])
|
9
|
+
opts << Compendium::Option.new(name: :boolean, type: :boolean)
|
10
|
+
opts << Compendium::Option.new(name: :another_boolean, type: :boolean)
|
11
|
+
opts
|
12
|
+
}
|
11
13
|
|
12
14
|
subject{ described_class.new(@params, options) }
|
13
15
|
|
@@ -25,4 +27,17 @@ describe Compendium::Params do
|
|
25
27
|
@params = {}
|
26
28
|
subject.ending_on.should be_nil
|
27
29
|
end
|
30
|
+
|
31
|
+
describe "#validations" do
|
32
|
+
let(:report_class) { Class.new(described_class) }
|
33
|
+
subject { report_class.new({}, options) }
|
34
|
+
|
35
|
+
before do
|
36
|
+
report_class.validates :ending_on, presence: true
|
37
|
+
subject.valid?
|
38
|
+
end
|
39
|
+
|
40
|
+
it { should_not be_valid }
|
41
|
+
its('errors.keys') { should include :ending_on }
|
42
|
+
end
|
28
43
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'compendium/presenters/chart'
|
3
|
+
|
4
|
+
describe Compendium::Presenters::Chart do
|
5
|
+
before do
|
6
|
+
described_class.any_instance.stub(:provider) { double('ChartProvider') }
|
7
|
+
described_class.any_instance.stub(:initialize_chart_provider)
|
8
|
+
end
|
9
|
+
|
10
|
+
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
|
+
context 'when all params are given' do
|
16
|
+
subject{ described_class.new(template, query, :pie, :container) }
|
17
|
+
|
18
|
+
its(:data) { should == results.records }
|
19
|
+
its(:container) { should == :container }
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when container is not given' do
|
23
|
+
subject{ described_class.new(template, query, :pie) }
|
24
|
+
|
25
|
+
its(:data) { should == results.records }
|
26
|
+
its(:container) { should == 'test_query' }
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when options are given" do
|
30
|
+
before { results.stub(:records) { { one: [] } } }
|
31
|
+
subject{ described_class.new(template, query, :pie, index: :one) }
|
32
|
+
|
33
|
+
its(:data) { should == results.records[:one] }
|
34
|
+
its(:container) { should == 'test_query' }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -15,7 +15,7 @@ describe Compendium::Presenters::Option do
|
|
15
15
|
|
16
16
|
describe "#name" do
|
17
17
|
it "should pass the name through I18n" do
|
18
|
-
template.should_receive(:t).with(
|
18
|
+
template.should_receive(:t).with('options.test_option', anything)
|
19
19
|
subject.name
|
20
20
|
end
|
21
21
|
end
|
data/spec/query_spec.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'spec_helper'
|
1
2
|
require 'compendium/query'
|
2
3
|
|
3
4
|
describe Compendium::Query do
|
@@ -48,50 +49,47 @@ describe Compendium::Query do
|
|
48
49
|
query = described_class.new(:blank, {}, nil)
|
49
50
|
query.run(nil).should be_empty
|
50
51
|
end
|
52
|
+
end
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
subject { described_class.new(:sub, {}, -> records { records.first }) }
|
58
|
-
|
59
|
-
before do
|
60
|
-
subject.stub(:get_through_query).with(:parent1).and_return(parent_query1)
|
61
|
-
subject.stub(:get_through_query).with(:parent2).and_return(parent_query2)
|
62
|
-
subject.stub(:get_through_query).with(:parent3).and_return(parent_query3)
|
63
|
-
described_class.any_instance.stub(:execute_query) { |cmd| cmd }
|
64
|
-
end
|
65
|
-
|
66
|
-
it "should not try to run a through query if the parent query has no results" do
|
67
|
-
subject.through = :parent1
|
54
|
+
describe "#nil?" do
|
55
|
+
it "should return true if the query's proc is nil" do
|
56
|
+
Compendium::Query.new(:test, {}, nil).should be_nil
|
57
|
+
end
|
68
58
|
|
69
|
-
|
70
|
-
|
71
|
-
|
59
|
+
it "should return false if the query's proc is not nil" do
|
60
|
+
Compendium::Query.new(:test, {}, ->{}).should_not be_nil
|
61
|
+
end
|
62
|
+
end
|
72
63
|
|
73
|
-
|
74
|
-
|
64
|
+
describe "#render_chart" do
|
65
|
+
let(:template) { double("Template") }
|
66
|
+
subject { described_class.new(:test, {}, -> * {}) }
|
75
67
|
|
76
|
-
|
77
|
-
|
78
|
-
|
68
|
+
it "should return nil if the query has no results" do
|
69
|
+
subject.stub(empty?: true)
|
70
|
+
subject.render_chart(template).should be_nil
|
71
|
+
end
|
79
72
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
end
|
73
|
+
it "should initialize a new Chart presenter if the query has results" do
|
74
|
+
subject.stub(empty?: false)
|
75
|
+
Compendium::Presenters::Chart.should_receive(:new).with(template, subject).and_return(double("Presenter").as_null_object)
|
76
|
+
subject.render_chart(template)
|
85
77
|
end
|
86
78
|
end
|
87
79
|
|
88
|
-
describe "#
|
89
|
-
|
90
|
-
|
80
|
+
describe "#render_table" do
|
81
|
+
let(:template) { double("Template") }
|
82
|
+
subject { described_class.new(:test, {}, -> * {}) }
|
83
|
+
|
84
|
+
it "should return nil if the query has no results" do
|
85
|
+
subject.stub(empty?: true)
|
86
|
+
subject.render_table(template).should be_nil
|
91
87
|
end
|
92
88
|
|
93
|
-
it "should
|
94
|
-
|
89
|
+
it "should initialize a new Table presenter if the query has results" do
|
90
|
+
subject.stub(empty?: false)
|
91
|
+
Compendium::Presenters::Table.should_receive(:new).with(template, subject).and_return(double("Presenter").as_null_object)
|
92
|
+
subject.render_table(template)
|
95
93
|
end
|
96
94
|
end
|
97
95
|
end
|
data/spec/report_spec.rb
CHANGED
@@ -129,4 +129,60 @@ describe Compendium::Report do
|
|
129
129
|
end
|
130
130
|
end
|
131
131
|
end
|
132
|
+
|
133
|
+
describe "predicate methods" do
|
134
|
+
before do
|
135
|
+
OneReport = Class.new(Compendium::Report)
|
136
|
+
TwoReport = Class.new(Compendium::Report)
|
137
|
+
ThreeReport = Class.new
|
138
|
+
end
|
139
|
+
|
140
|
+
after do
|
141
|
+
Object.send(:remove_const, :OneReport)
|
142
|
+
Object.send(:remove_const, :TwoReport)
|
143
|
+
Object.send(:remove_const, :ThreeReport)
|
144
|
+
end
|
145
|
+
|
146
|
+
it { should respond_to(:one?) }
|
147
|
+
it { should respond_to(:two?) }
|
148
|
+
it { should_not respond_to(:three?) }
|
149
|
+
|
150
|
+
it { should_not be_one }
|
151
|
+
it { should_not be_two }
|
152
|
+
|
153
|
+
specify { OneReport.should be_one }
|
154
|
+
specify { TwoReport.should be_two }
|
155
|
+
end
|
156
|
+
|
157
|
+
describe "parameters" do
|
158
|
+
let(:report_class) { Class.new(subject) }
|
159
|
+
let(:report_class2) { Class.new(report_class) }
|
160
|
+
|
161
|
+
it "should include ancestors params" do
|
162
|
+
report_class.params_class.ancestors.should include subject.params_class
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should inherit validations" do
|
166
|
+
report_class.params_class.validates :foo, presence: true
|
167
|
+
report_class2.params_class.validators_on(:foo).should_not be_nil
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
describe "#valid?" do
|
172
|
+
let(:report_class) do
|
173
|
+
Class.new(described_class) do
|
174
|
+
option :id, :dropdown, choices: (0..10).to_a, validates: { presence: true }
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should return true if there are no validation failures" do
|
179
|
+
r = report_class.new(id: 5)
|
180
|
+
r.should be_valid
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should return false if there are validation failures" do
|
184
|
+
r = report_class.new(id: nil)
|
185
|
+
r.should_not be_valid
|
186
|
+
end
|
187
|
+
end
|
132
188
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'compendium/result_set'
|
2
|
+
|
3
|
+
describe Compendium::ResultSet do
|
4
|
+
describe "#initialize" do
|
5
|
+
subject{ described_class.new(results).records }
|
6
|
+
|
7
|
+
context "when given an array" do
|
8
|
+
let(:results) { [1, 2, 3] }
|
9
|
+
it { should == [1, 2, 3] }
|
10
|
+
end
|
11
|
+
|
12
|
+
context "when given an array of hashes" do
|
13
|
+
let(:results) { [{one: 1}, {two: 2}] }
|
14
|
+
it { should == [{"one" => 1}, {"two" => 2}] }
|
15
|
+
its(:first) { should be_a ActiveSupport::HashWithIndifferentAccess }
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when given a hash" do
|
19
|
+
let(:results) { { one: 1, two: 2 } }
|
20
|
+
it { should == { one: 1, two: 2 } }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'compendium/through_query'
|
2
|
+
|
3
|
+
describe Compendium::ThroughQuery do
|
4
|
+
describe "#initialize" do
|
5
|
+
let(:options) { double("Options") }
|
6
|
+
let(:proc) { double("Proc") }
|
7
|
+
let(:through) { double("Query") }
|
8
|
+
|
9
|
+
context "when supplying a report" do
|
10
|
+
let(:r) { Compendium::Report.new }
|
11
|
+
subject { described_class.new(r, :test, through, options, proc)}
|
12
|
+
|
13
|
+
its(:report) { should == r }
|
14
|
+
its(:name) { should == :test }
|
15
|
+
its(:through) { should == through }
|
16
|
+
its(:options) { should == options }
|
17
|
+
its(:proc) { should == proc }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when not supplying a report" do
|
21
|
+
subject { described_class.new(:test, through, options, proc)}
|
22
|
+
|
23
|
+
its(:report) { should be_nil }
|
24
|
+
its(:name) { should == :test }
|
25
|
+
its(:through) { should == through }
|
26
|
+
its(:options) { should == options }
|
27
|
+
its(:proc) { should == proc }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#run" do
|
32
|
+
let(:parent1) { Compendium::Query.new(:parent1, {}, -> * { }) }
|
33
|
+
let(:parent2) { Compendium::Query.new(:parent2, {}, -> * { }) }
|
34
|
+
let(:parent3) { Compendium::Query.new(:parent3, {}, -> * { [[1, 2, 3]] }) }
|
35
|
+
|
36
|
+
before { parent3.stub(:execute_query) { |cmd| cmd } }
|
37
|
+
|
38
|
+
context "with a single parent" do
|
39
|
+
subject { described_class.new(:sub, parent1, {}, -> r { r.first }) }
|
40
|
+
|
41
|
+
it "should not try to run a through query if the parent query has no results" do
|
42
|
+
expect { subject.run(nil) }.to_not raise_error
|
43
|
+
subject.results.should be_empty
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "with multiple parents" do
|
48
|
+
subject { described_class.new(:sub, [parent1, parent2], {}, -> r { r.first }) }
|
49
|
+
|
50
|
+
it "should not try to run a through query with multiple parents all of which have no results" do
|
51
|
+
expect { subject.run(nil) }.to_not raise_error
|
52
|
+
subject.results.should be_empty
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should allow non blank queries" do
|
56
|
+
subject.through = parent3
|
57
|
+
subject.run(nil)
|
58
|
+
subject.results.should == [1, 2, 3]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when the through option is an actual query" do
|
63
|
+
subject { described_class.new(:sub, parent3, {}, -> r { r.first }) }
|
64
|
+
|
65
|
+
before { subject.run(nil) }
|
66
|
+
|
67
|
+
its(:through) { should == parent3 }
|
68
|
+
its(:results) { should == [1, 2, 3] }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
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.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Vandersluis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-11-
|
11
|
+
date: 2013-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
type: :runtime
|
@@ -60,12 +60,12 @@ dependencies:
|
|
60
60
|
requirements:
|
61
61
|
- - '='
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version: 1.0.
|
63
|
+
version: 1.0.5
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - '='
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 1.0.
|
68
|
+
version: 1.0.5
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
type: :runtime
|
71
71
|
prerelease: false
|
@@ -129,6 +129,7 @@ files:
|
|
129
129
|
- lib/compendium.rb
|
130
130
|
- lib/compendium/abstract_chart_provider.rb
|
131
131
|
- lib/compendium/chart_provider/amcharts.rb
|
132
|
+
- lib/compendium/collection_query.rb
|
132
133
|
- lib/compendium/context_wrapper.rb
|
133
134
|
- lib/compendium/dsl.rb
|
134
135
|
- lib/compendium/engine.rb
|
@@ -141,7 +142,9 @@ files:
|
|
141
142
|
- lib/compendium/query.rb
|
142
143
|
- lib/compendium/report.rb
|
143
144
|
- lib/compendium/result_set.rb
|
145
|
+
- lib/compendium/through_query.rb
|
144
146
|
- lib/compendium/version.rb
|
147
|
+
- spec/collection_query_spec.rb
|
145
148
|
- spec/context_wrapper_spec.rb
|
146
149
|
- spec/dsl_spec.rb
|
147
150
|
- spec/metric_spec.rb
|
@@ -149,10 +152,13 @@ files:
|
|
149
152
|
- spec/param_types_spec.rb
|
150
153
|
- spec/params_spec.rb
|
151
154
|
- spec/presenters/base_spec.rb
|
155
|
+
- spec/presenters/chart_spec.rb
|
152
156
|
- spec/presenters/option_spec.rb
|
153
157
|
- spec/query_spec.rb
|
154
158
|
- spec/report_spec.rb
|
159
|
+
- spec/result_set_spec.rb
|
155
160
|
- spec/spec_helper.rb
|
161
|
+
- spec/through_query_spec.rb
|
156
162
|
homepage: https://github.com/dvandersluis/compendium
|
157
163
|
licenses:
|
158
164
|
- MIT
|
@@ -178,6 +184,7 @@ signing_key:
|
|
178
184
|
specification_version: 4
|
179
185
|
summary: Ruby on Rails reporting framework
|
180
186
|
test_files:
|
187
|
+
- spec/collection_query_spec.rb
|
181
188
|
- spec/context_wrapper_spec.rb
|
182
189
|
- spec/dsl_spec.rb
|
183
190
|
- spec/metric_spec.rb
|
@@ -185,8 +192,11 @@ test_files:
|
|
185
192
|
- spec/param_types_spec.rb
|
186
193
|
- spec/params_spec.rb
|
187
194
|
- spec/presenters/base_spec.rb
|
195
|
+
- spec/presenters/chart_spec.rb
|
188
196
|
- spec/presenters/option_spec.rb
|
189
197
|
- spec/query_spec.rb
|
190
198
|
- spec/report_spec.rb
|
199
|
+
- spec/result_set_spec.rb
|
191
200
|
- spec/spec_helper.rb
|
201
|
+
- spec/through_query_spec.rb
|
192
202
|
has_rdoc:
|