compendium 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
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