compendium 1.0.1 → 1.0.2

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- Y2ExNjQ1Y2U2ZjhiZTQ4ZDg4NjI1MmU5NmYxODFmNDYzMDI2MzI0Yw==
4
+ Y2M5ZWFmZjNlN2Q0YWQ0MGQ4ZTQ0Njg3ZDIzN2VjMTI4NzZlOTJlYw==
5
5
  data.tar.gz: !binary |-
6
- OTFhMGQ1Y2U0ZGE5YzM4YWQ0NDg3ODlmZDgwYjU3YmFiYjY0MmNjNA==
6
+ ZjFkNjcwNmU2YTRlOTNhZTdiZjYyYmU0MzA1MDEzZGJhMjdmOGQ3MQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- YzExMTE2ZjI3ZmZiZGM0OTgyMjQ5NWRmN2I4M2U3YTU1ZTI5OTlkZDhlZGJk
10
- Y2Y5YTRmYWI2ZGRlM2JiYTY1MWIxNGNlZDMwZDNmMGRlNGZmZmU5MjNjNjU3
11
- OGJkYTQ3MWRmMzQxZWEyNGY2NTcwMTZjNDhlYzgwNzJmN2UwMzc=
9
+ NjlmNzliZjA5MjU3N2E4Mzk2NzZkOWM0M2JmM2YzYzk1YWNjNDQ1MjgyZTc3
10
+ MGFkNzM5ODc4YzI1NGUyMzM1ZDliMWE1ZDY5NmQ2YTQzMjFkNjgzOGNiMzQy
11
+ ZGM3NWI5OTA5YjlhMGY0YzMwMjYwNzYzNjJiYjQ5ODE1MDY0NTM=
12
12
  data.tar.gz: !binary |-
13
- NGNmMWQ3YzllM2E2MDBjZTY3MWI3YTEzZTY3NGRkNDA5MzdjNzk5Y2U5MjRm
14
- MWM2OWZiZGJjZjljNjc1NWIzYTcxODBmMDk2NWRkNTc1NmM5NmJmZmVhMzEx
15
- YzQyNDE0Nzk2MWNjM2U0MzY4NjdjZjdlOTgyYWE3NmU2Y2VmNDI=
13
+ ODAwYmEwOTJhMmViNTczMTQ4ZGNmYTY0ZGZmZjNjZTZkYjJjMTAwNzNiYjgx
14
+ ZmEyOTA0MDRjNmFkMWNiMWM5NzQ3ZTYyYzkzMDlmYzY4ZTk0YTczOTgyZTgy
15
+ MTc3ODZmYjU4NGY1MDA4NGJmMjVmNDgyNjIzOTE5YzcyY2Y4NzA=
@@ -4,7 +4,7 @@ div.metrics
4
4
  {
5
5
  div.metric
6
6
  {
7
- float: left;
7
+ display: inline-block;
8
8
  margin: 10px;
9
9
  padding: 5px;
10
10
  border: 2px solid #575757;
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.3'
24
+ gem.add_dependency 'collection_of', '1.0.4'
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,6 @@
1
+ class Hash
2
+ # Remove nil values
3
+ def compact
4
+ delete_if{ |_, v| v.blank? }
5
+ end unless method_defined?(:compact)
6
+ end
@@ -22,6 +22,7 @@ module Compendium
22
22
 
23
23
  if options[name]
24
24
  options[name].type = type if type
25
+ options[name].default = opts.delete(:default) if opts.key?(:default)
25
26
  options[name].merge!(opts)
26
27
  else
27
28
  options[name] = Compendium::Option.new(opts.merge(name: name, type: type))
@@ -5,7 +5,7 @@ require 'active_support/core_ext/module/delegation'
5
5
 
6
6
  module Compendium
7
7
  class Option
8
- attr_reader :name, :type, :default, :choices, :options
8
+ attr_accessor :name, :type, :default, :choices, :options
9
9
 
10
10
  delegate :boolean?, :date?, :dropdown?, :radio?, :text?, to: :type
11
11
  delegate :merge, :merge!, :[], to: :@options
@@ -1,16 +1,19 @@
1
1
  require 'compendium/result_set'
2
2
  require 'compendium/params'
3
3
  require 'collection_of'
4
+ require_relative '../../config/initializers/ruby/hash'
4
5
 
5
6
  module Compendium
6
7
  class Query
7
8
  attr_reader :name, :results, :metrics
8
9
  attr_accessor :options, :proc, :through, :report
9
10
 
10
- def initialize(name, options, proc)
11
- @name = name
12
- @options = options
13
- @proc = proc
11
+ def initialize(*args)
12
+ @report = args.shift if arg_is_report?(args.first)
13
+
14
+ raise ArgumentError, "wrong number of arguments (#{args.size + (@report ? 1 : 0)} for 3..4)" unless args.size == 3
15
+
16
+ @name, @options, @proc = args
14
17
  @metrics = ::Collection[Metric]
15
18
  end
16
19
 
@@ -50,10 +53,14 @@ module Compendium
50
53
  private
51
54
 
52
55
  def collect_results(params, context)
53
- args = if through.nil?
54
- params
56
+ if through.nil?
57
+ args = params
55
58
  else
56
- collect_through_query_results(through, params, context)
59
+ args = collect_through_query_results(through, params, context)
60
+
61
+ # If none of the through queries have any results, we shouldn't try to execute the query, because it
62
+ # depends on the results of its parents.
63
+ return @results = ResultSet.new([]) if args.compact.empty?
57
64
  end
58
65
 
59
66
  command = context.instance_exec(args, &proc) if proc
@@ -69,10 +76,20 @@ module Compendium
69
76
  if options.key?(:through) or options.fetch(:collect, nil) == :active_record
70
77
  command
71
78
  else
72
- ::ActiveRecord::Base.connection.select_all(command.respond_to?(:to_sql) ? command.to_sql : command)
79
+ execute_command(command)
73
80
  end
74
81
  end
75
82
 
83
+ def execute_command(command)
84
+ return [] if command.nil?
85
+ command = command.to_sql if command.respond_to?(:to_sql)
86
+ execute_query(command)
87
+ end
88
+
89
+ def execute_query(command)
90
+ ::ActiveRecord::Base.connection.select_all(command)
91
+ end
92
+
76
93
  def collect_through_query_results(through, params, context)
77
94
  results = {}
78
95
 
@@ -90,5 +107,9 @@ module Compendium
90
107
  def get_through_query(name)
91
108
  report.queries[name]
92
109
  end
110
+
111
+ def arg_is_report?(arg)
112
+ arg.is_a?(Report) or (arg.is_a?(Class) and arg < Report)
113
+ end
93
114
  end
94
115
  end
@@ -19,11 +19,25 @@ module Compendium
19
19
  queries.each { |q| q.report = self }
20
20
  end
21
21
 
22
- def run(context = nil)
22
+ def run(context = nil, options = {})
23
23
  self.context = context
24
24
  self.results = {}
25
25
 
26
- queries.each{ |q| self.results[q.name] = q.run(params, ContextWrapper.wrap(context, self)) }
26
+ only = options.delete(:only)
27
+ except = options.delete(:except)
28
+
29
+ raise ArgumentError, 'cannot specify only and except options at the same time' if only && except
30
+ ([only] + [except]).flatten.compact.each { |q| raise ArgumentError, 'invalid query #{q}' unless queries.include?(q) }
31
+
32
+ queries_to_run = if only
33
+ queries.slice(only)
34
+ elsif except
35
+ queries.except(except)
36
+ else
37
+ queries
38
+ end
39
+
40
+ queries_to_run.each{ |q| self.results[q.name] = q.run(params, ContextWrapper.wrap(context, self)) }
27
41
 
28
42
  self
29
43
  end
@@ -1,3 +1,3 @@
1
1
  module Compendium
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.2"
3
3
  end
data/spec/dsl_spec.rb CHANGED
@@ -19,6 +19,12 @@ describe Compendium::DSL do
19
19
  subject.options[:starting_on].should be_boolean
20
20
  subject.options[:starting_on].should_not be_date
21
21
  end
22
+
23
+ it "should allow overriding default value" do
24
+ proc = -> { Date.new(2013, 6, 1) }
25
+ subject.option :starting_on, :date, default: proc
26
+ subject.options[:starting_on].default.should == proc
27
+ end
22
28
  end
23
29
 
24
30
  describe "#query" do
data/spec/query_spec.rb CHANGED
@@ -1,6 +1,30 @@
1
1
  require 'compendium/query'
2
2
 
3
3
  describe Compendium::Query do
4
+ describe "#initialize" do
5
+ let(:options) { double("Options") }
6
+ let(:proc) { double("Proc") }
7
+
8
+ context "when supplying a report" do
9
+ let(:r) { Compendium::Report.new }
10
+ subject { described_class.new(r, :test, options, proc)}
11
+
12
+ its(:report) { should == r }
13
+ its(:name) { should == :test }
14
+ its(:options) { should == options }
15
+ its(:proc) { should == proc }
16
+ end
17
+
18
+ context "when not supplying a report" do
19
+ subject { described_class.new(:test, options, proc)}
20
+
21
+ its(:report) { should be_nil }
22
+ its(:name) { should == :test }
23
+ its(:options) { should == options }
24
+ its(:proc) { should == proc }
25
+ end
26
+ end
27
+
4
28
  describe "#run" do
5
29
  let(:query) { described_class.new(:test, {}, -> * { [1, 2, 3] }) }
6
30
  before { query.stub(:fetch_results) { |c| c } }
@@ -19,6 +43,46 @@ describe Compendium::Query do
19
43
  query.run(nil)
20
44
  q2.should_not have_run
21
45
  end
46
+
47
+ it "should return an empty result set if running an query with no proc" do
48
+ query = described_class.new(:blank, {}, nil)
49
+ query.run(nil).should be_empty
50
+ end
51
+
52
+ context 'through queries' do
53
+ let(:parent_query1) { described_class.new(:parent1, {}, -> * { }) }
54
+ let(:parent_query2) { described_class.new(:parent2, {}, -> * { }) }
55
+ let(:parent_query3) { described_class.new(:parent3, {}, -> * { [[1, 2, 3]] }) }
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
68
+
69
+ expect { subject.run(nil) }.to_not raise_error
70
+ subject.results.should be_empty
71
+ end
72
+
73
+ it "should not try to run a through query with multiple parents all of which have no results" do
74
+ subject.through = [:parent1, :parent2]
75
+
76
+ expect { subject.run(nil) }.to_not raise_error
77
+ subject.results.should be_empty
78
+ end
79
+
80
+ it "should allow non blank queries" do
81
+ subject.through = :parent3
82
+ subject.run(nil)
83
+ subject.results.should == [1, 2, 3]
84
+ end
85
+ end
22
86
  end
23
87
 
24
88
  describe "#nil?" do
data/spec/report_spec.rb CHANGED
@@ -29,64 +29,103 @@ describe Compendium::Report do
29
29
  end
30
30
 
31
31
  describe "#run" do
32
- let(:report_class) do
33
- Class.new(Compendium::Report) do
34
- option :first, :date
35
- option :second, :date
32
+ context do
33
+ let(:report_class) do
34
+ Class.new(Compendium::Report) do
35
+ option :first, :date
36
+ option :second, :date
36
37
 
37
- query :test do |params|
38
- [params[:first].__getobj__, params[:second].__getobj__]
38
+ query :test do |params|
39
+ [params[:first].__getobj__, params[:second].__getobj__]
40
+ end
41
+
42
+ metric :test_metric, -> results { results.to_a.max }, through: :test
39
43
  end
44
+ end
45
+
46
+ subject { report_class.new(first: '2010-10-10', second: '2011-11-11') }
47
+ let!(:report2) { report_class.new }
40
48
 
41
- metric :test_metric, -> results { results.to_a.max }, through: :test
49
+ before do
50
+ Compendium::Query.any_instance.stub(:fetch_results) { |c| c }
51
+ subject.run
42
52
  end
43
- end
44
53
 
45
- subject { report_class.new(first: '2010-10-10', second: '2011-11-11') }
46
- let!(:report2) { report_class.new }
54
+ its('test_results.records') { should == [Date.new(2010, 10, 10), Date.new(2011, 11, 11)] }
47
55
 
48
- before do
49
- Compendium::Query.any_instance.stub(:fetch_results) { |c| c }
50
- subject.run
51
- end
56
+ it "should run its metrics" do
57
+ subject.test.metrics[:test_metric].result.should == Date.new(2011, 11, 11)
58
+ subject.metrics[:test_metric].result.should == Date.new(2011, 11, 11)
59
+ end
52
60
 
53
- its('test_results.records') { should == [Date.new(2010, 10, 10), Date.new(2011, 11, 11)] }
61
+ it "should not affect other instances of the report class" do
62
+ report2.test.results.should be_nil
63
+ report2.metrics[:test_metric].result.should be_nil
64
+ end
54
65
 
55
- it "should run its metrics" do
56
- subject.test.metrics[:test_metric].result.should == Date.new(2011, 11, 11)
57
- subject.metrics[:test_metric].result.should == Date.new(2011, 11, 11)
58
- end
66
+ it "should not affect the class collections" do
67
+ report_class.test.results.should be_nil
68
+ end
59
69
 
60
- it "should not affect other instances of the report class" do
61
- report2.test.results.should be_nil
62
- report2.metrics[:test_metric].result.should be_nil
63
- end
70
+ context "with through queries" do
71
+ let(:report_class) do
72
+ Class.new(Compendium::Report) do
73
+ option :first, :boolean, default: false
74
+ query(:test) { |params| !!params[:first] ? [100, 200, 400, 800] : [1600, 3200, 6400]}
75
+ query(:through, through: :test) { |results| [results.first] }
76
+ end
77
+ end
78
+
79
+ subject { report_class.new(first: true) }
80
+
81
+ its('through.results') { should == [100] }
64
82
 
65
- it "should not affect the class collections" do
66
- report_class.test.results.should be_nil
83
+ it "should not mark other instances' queries as ran" do
84
+ report2.test.should_not have_run
85
+ end
86
+
87
+ it "should not affect other instances" do
88
+ report2.queries.each { |q| q.stub(:fetch_results) { |c| c } }
89
+ report2.run
90
+ report2.through.results.should == [1600]
91
+ end
92
+ end
67
93
  end
68
94
 
69
- context "with through queries" do
95
+ context "when specifying which queries to run" do
70
96
  let(:report_class) do
71
97
  Class.new(Compendium::Report) do
72
- option :first, :boolean, default: false
73
- query(:test) { |params| !!params[:first] ? [100, 200, 400, 800] : [1600, 3200, 6400]}
74
- query(:through, through: :test) { |results| [results.first] }
98
+ query :first
99
+ query :second
75
100
  end
76
101
  end
77
102
 
78
- subject { report_class.new(first: true) }
103
+ subject { report_class.new }
104
+
105
+ it "should raise an error if given :only and :except options" do
106
+ expect{ subject.run(nil, only: :first, except: :second) }.to raise_error(ArgumentError)
107
+ end
108
+
109
+ it "should raise an error if given an invalid query name" do
110
+ expect{ subject.run(nil, only: :foo) }.to raise_error(ArgumentError)
111
+ end
79
112
 
80
- its('through.results') { should == [100] }
113
+ it "should run all queries if nothing is specified" do
114
+ subject.run(nil)
115
+ subject.first.should have_run
116
+ subject.second.should have_run
117
+ end
81
118
 
82
- it "should not mark other instances' queries as ran" do
83
- report2.test.should_not have_run
119
+ it "should only run queries specified by :only" do
120
+ subject.run(nil, only: :first)
121
+ subject.first.should have_run
122
+ subject.second.should_not have_run
84
123
  end
85
124
 
86
- it "should not affect other instances" do
87
- report2.queries.each { |q| q.stub(:fetch_results) { |c| c } }
88
- report2.run
89
- report2.through.results.should == [1600]
125
+ it "should not run queries specified by :except" do
126
+ subject.run(nil, except: :first)
127
+ subject.first.should_not have_run
128
+ subject.second.should have_run
90
129
  end
91
130
  end
92
131
  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.1
4
+ version: 1.0.2
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-10-30 00:00:00.000000000 Z
11
+ date: 2013-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  type: :runtime
@@ -58,14 +58,14 @@ dependencies:
58
58
  name: collection_of
59
59
  requirement: !ruby/object:Gem::Requirement
60
60
  requirements:
61
- - - ! '>='
61
+ - - '='
62
62
  - !ruby/object:Gem::Version
63
- version: 1.0.3
63
+ version: 1.0.4
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ! '>='
66
+ - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: 1.0.3
68
+ version: 1.0.4
69
69
  - !ruby/object:Gem::Dependency
70
70
  type: :runtime
71
71
  prerelease: false
@@ -123,6 +123,7 @@ files:
123
123
  - app/views/compendium/reports/setup.haml
124
124
  - compendium.gemspec
125
125
  - config/initializers/rails/active_record/connection_adapters/quoting.rb
126
+ - config/initializers/ruby/hash.rb
126
127
  - config/initializers/ruby/numeric.rb
127
128
  - config/locales/en.yml
128
129
  - lib/compendium.rb