kpi 0.5.4 → 0.5.5

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.
@@ -1,12 +1,13 @@
1
1
  module KPI
2
2
  class MergedReport
3
+
3
4
  def initialize(*args, &block)
5
+ options = args.extract_options!
4
6
  raise ArgumentError, "Should have any argument" if args.length == 0
5
7
  raise Exception unless block_given?
6
- raise ArgumentError, "Argument must be the same type" unless args.map(&:class).uniq.size == 1
7
-
8
- @reports ||= args
9
- @compare = block
8
+ @_mode = options[:mode] || :&
9
+ @_reports = args
10
+ @_merge = block
10
11
  end
11
12
 
12
13
  def entries
@@ -22,18 +23,40 @@ module KPI
22
23
  end
23
24
 
24
25
  def defined_kpis
25
- @reports.map(&:defined_kpis).inject(&:&)
26
+ # takes all reports and uses & (default) or | operator for inject function
27
+ # to build list of defined KPIs
28
+ @_reports.map(&:defined_kpis).inject(&@_mode).map(&:to_sym)
26
29
  end
27
30
 
28
31
  def method_missing(name, *args)
29
- result = @compare.call(*@reports.map(&name.to_sym))
30
- orginal = @reports.first.send(name.to_sym)
31
- description = (orginal.description && result.description ? result.description.gsub("$$", orginal.description) : nil)
32
+ return kpi_exists?($1) if (/(.*)\?/ =~ name.to_s) # check if KPI exists in report if name of missing method has trailing '?'
33
+ result = merge_proc_call(name)
34
+ orginal = @_reports.find(&:"#{name}?").send(name) # find first report having requested KPI
35
+ description = if orginal.description && result.description # if description exists in orginal and result Entries
36
+ result.description.gsub("$$", orginal.description)
37
+ else nil
38
+ end
32
39
 
33
40
  KPI::Entry.new(result.name.gsub("$$", orginal.name),
34
41
  result.value,
35
42
  :description => description,
36
43
  :unit => (result.unit || orginal.unit))
37
44
  end
45
+
46
+ private
47
+
48
+ def kpi_exists?(name)
49
+ self.defined_kpis.include?(name.to_sym)
50
+ end
51
+
52
+ def merge_proc_call(name)
53
+ sym_name = name.to_sym
54
+ args = @_mode == :& ? @_reports.map(&sym_name) : begin # if report is in intersection mode, query for an KPI, otherwise
55
+ @_reports.map do |report| # for each report
56
+ report.send("#{name}?") ? report.send(name) : nil # if it has requested kpi return it's result, otherwise: nil
57
+ end
58
+ end
59
+ @_merge.call(*args) # call merge proc with according KPIs
60
+ end
38
61
  end
39
62
  end
@@ -5,7 +5,7 @@ module KPI
5
5
 
6
6
  include KPI::Report::DynamicDefinitions
7
7
 
8
- blacklist :initialize, :collect!, :entries, :time, :title, :defined_kpis, :result
8
+ blacklist :initialize, :collect!, :entries, :time, :title, :defined_kpis, :result, :method_missing
9
9
 
10
10
  def initialize(*args)
11
11
  @options = args.extract_options!
@@ -31,11 +31,23 @@ module KPI
31
31
  end
32
32
 
33
33
  def defined_kpis
34
- self.class.defined_kpis
34
+ self.class.defined_kpis.map(&:to_sym)
35
35
  end
36
-
36
+
37
37
  def result(*args)
38
38
  KPI::Entry.new *args
39
39
  end
40
+
41
+ def method_missing(name, *args)
42
+ # check if KPI exists in report if name of missing method has trailing '?'
43
+ return kpi_exists?($1.to_sym) if (/(.*)\?/ =~ name.to_s)
44
+ super
45
+ end
46
+
47
+ private
48
+
49
+ def kpi_exists?(name)
50
+ self.defined_kpis.include?(name.to_sym)
51
+ end
40
52
  end
41
- end
53
+ end
@@ -18,6 +18,13 @@ describe "KPI::MergedReport" do
18
18
  end
19
19
  end
20
20
  class AnotherReport < KPI::Report
21
+ def test_kpi
22
+ result "title", 3, :description => "description"
23
+ end
24
+
25
+ def another_kpi
26
+ result "another", 5
27
+ end
21
28
  end
22
29
  end
23
30
 
@@ -39,10 +46,8 @@ describe "KPI::MergedReport" do
39
46
  end
40
47
  end
41
48
 
42
- it "should require objects of the same type when initializing" do
43
- assert_raises(ArgumentError) do
44
- KPI::MergedReport.new(TestKpi.new, AnotherReport.new) {}
45
- end
49
+ it "should allow objects of the same type when initializing" do
50
+ KPI::MergedReport.new(TestKpi.new, AnotherReport.new) {}
46
51
  end
47
52
 
48
53
  it "should require block when initializing" do
@@ -52,7 +57,7 @@ describe "KPI::MergedReport" do
52
57
  end
53
58
  end
54
59
 
55
- describe "when two reports given for average" do
60
+ describe "when two identical reports given for average" do
56
61
  before do
57
62
  @report1 = TestKpi.new(2)
58
63
  @report2 = TestKpi.new(8)
@@ -113,6 +118,62 @@ describe "KPI::MergedReport" do
113
118
  it "should return KPIs defined by all compounds" do
114
119
  assert_equal TestKpi.defined_kpis, @average.defined_kpis
115
120
  end
121
+
122
+ it "should check if defined_kpis return array of symbol" do
123
+ assert_same true, @average.defined_kpis.map(&:class).uniq === [Symbol]
124
+ end
125
+
126
+ it "should return true when calling test_kpi?" do
127
+ assert @average.test_kpi?
128
+ end
129
+
130
+ it "should return false when calling non existing method with '?'" do
131
+ assert !@average.test_kpi_23?
132
+ end
133
+ end
134
+ end
135
+
136
+ describe "when different reports given for merge" do
137
+ before do
138
+ @report1 = TestKpi.new(2)
139
+ @report2 = AnotherReport.new
140
+ end
141
+
142
+ describe "when intersection" do
143
+ before do
144
+ @merge = KPI::MergedReport.new(@report1, @report2) do |test, another|
145
+ KPI::Entry.new "$$", {:test => test, :another => another}, :description => '$$'
146
+ end
147
+ end
148
+
149
+ it "should have only common KPI defined" do
150
+ assert_equal [:test_kpi], @merge.defined_kpis
151
+ end
152
+
153
+ it "should not repospond for not common KPI" do
154
+ assert_raises(NoMethodError) { @merge.another_kpi }
155
+ end
156
+
157
+ it "should return values for common KPI" do
158
+ assert_instance_of Hash, @merge.test_kpi.value
159
+ end
160
+ end
161
+
162
+ describe "when conjunction" do
163
+ before do
164
+ @merge = KPI::MergedReport.new(@report1, @report2, :mode => :|) do |test, another|
165
+ merge = {:test => test.try(:value), :another => another.try(:value)}
166
+ KPI::Entry.new "$$", merge, :description => '$$'
167
+ end
168
+ end
169
+
170
+ it "should have all KPI of both reports" do
171
+ assert_equal [:test_kpi, :test_kpi_2, :another_kpi], @merge.defined_kpis
172
+ end
173
+
174
+ it "should return KPI" do
175
+ assert_equal({:test => nil, :another => 5}, @merge.another_kpi.value)
176
+ end
116
177
  end
117
178
  end
118
179
  end
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kpi
3
3
  version: !ruby/object:Gem::Version
4
- hash: 3
5
4
  prerelease:
6
- segments:
7
- - 0
8
- - 5
9
- - 4
10
- version: 0.5.4
5
+ version: 0.5.5
11
6
  platform: ruby
12
7
  authors:
13
8
  - Artur Roszczyk
@@ -15,98 +10,75 @@ autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
12
 
18
- date: 2011-05-15 00:00:00 +02:00
13
+ date: 2011-05-16 00:00:00 +02:00
19
14
  default_executable:
20
15
  dependencies:
21
16
  - !ruby/object:Gem::Dependency
22
17
  name: actionmailer
23
- version_requirements: &id001 !ruby/object:Gem::Requirement
18
+ requirement: &id001 !ruby/object:Gem::Requirement
24
19
  none: false
25
20
  requirements:
26
21
  - - ">="
27
22
  - !ruby/object:Gem::Version
28
- hash: 5
29
- segments:
30
- - 2
31
- - 3
32
23
  version: "2.3"
33
- prerelease: false
34
24
  type: :runtime
35
- requirement: *id001
25
+ prerelease: false
26
+ version_requirements: *id001
36
27
  - !ruby/object:Gem::Dependency
37
28
  name: activesupport
38
- version_requirements: &id002 !ruby/object:Gem::Requirement
29
+ requirement: &id002 !ruby/object:Gem::Requirement
39
30
  none: false
40
31
  requirements:
41
32
  - - ">="
42
33
  - !ruby/object:Gem::Version
43
- hash: 5
44
- segments:
45
- - 2
46
- - 3
47
34
  version: "2.3"
48
- prerelease: false
49
35
  type: :runtime
50
- requirement: *id002
36
+ prerelease: false
37
+ version_requirements: *id002
51
38
  - !ruby/object:Gem::Dependency
52
39
  name: minitest
53
- version_requirements: &id003 !ruby/object:Gem::Requirement
40
+ requirement: &id003 !ruby/object:Gem::Requirement
54
41
  none: false
55
42
  requirements:
56
43
  - - ">="
57
44
  - !ruby/object:Gem::Version
58
- hash: 3
59
- segments:
60
- - 0
61
45
  version: "0"
62
- prerelease: false
63
46
  type: :development
64
- requirement: *id003
47
+ prerelease: false
48
+ version_requirements: *id003
65
49
  - !ruby/object:Gem::Dependency
66
50
  name: bundler
67
- version_requirements: &id004 !ruby/object:Gem::Requirement
51
+ requirement: &id004 !ruby/object:Gem::Requirement
68
52
  none: false
69
53
  requirements:
70
54
  - - ~>
71
55
  - !ruby/object:Gem::Version
72
- hash: 15
73
- segments:
74
- - 1
75
- - 0
76
56
  version: "1.0"
77
- prerelease: false
78
57
  type: :development
79
- requirement: *id004
58
+ prerelease: false
59
+ version_requirements: *id004
80
60
  - !ruby/object:Gem::Dependency
81
61
  name: jeweler
82
- version_requirements: &id005 !ruby/object:Gem::Requirement
62
+ requirement: &id005 !ruby/object:Gem::Requirement
83
63
  none: false
84
64
  requirements:
85
65
  - - ~>
86
66
  - !ruby/object:Gem::Version
87
- hash: 7
88
- segments:
89
- - 1
90
- - 5
91
- - 2
92
67
  version: 1.5.2
93
- prerelease: false
94
68
  type: :development
95
- requirement: *id005
69
+ prerelease: false
70
+ version_requirements: *id005
96
71
  - !ruby/object:Gem::Dependency
97
72
  name: rcov
98
- version_requirements: &id006 !ruby/object:Gem::Requirement
73
+ requirement: &id006 !ruby/object:Gem::Requirement
99
74
  none: false
100
75
  requirements:
101
76
  - - ">="
102
77
  - !ruby/object:Gem::Version
103
- hash: 3
104
- segments:
105
- - 0
106
78
  version: "0"
107
- prerelease: false
108
79
  type: :development
109
- requirement: *id006
80
+ prerelease: false
81
+ version_requirements: *id006
110
82
  description: This gem helps you to track key indicators in your Rails app.
111
83
  email: artur.roszczyk@gmail.com
112
84
  executables: []
@@ -148,7 +120,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
148
120
  requirements:
149
121
  - - ">="
150
122
  - !ruby/object:Gem::Version
151
- hash: 3
123
+ hash: -4102410912308546025
152
124
  segments:
153
125
  - 0
154
126
  version: "0"
@@ -157,9 +129,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
129
  requirements:
158
130
  - - ">="
159
131
  - !ruby/object:Gem::Version
160
- hash: 3
161
- segments:
162
- - 0
163
132
  version: "0"
164
133
  requirements: []
165
134