kpi 0.5.0 → 0.5.1

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,4 +1,15 @@
1
1
  module KPI
2
- class Entry < Struct.new(:name, :value, :description)
2
+ class Entry
3
+ attr_reader :name, :value, :description
4
+ def initialize(*args)
5
+ options = args.extract_options!
6
+ raise ArgumentError, "Wrong number of arguments (#{args.count} of 2)" unless args.count == 2
7
+ @name, @value = args
8
+ @description = options[:description]
9
+ end
10
+
11
+ def to_a
12
+ [@title, @value, @description].compact
13
+ end
3
14
  end
4
15
  end
@@ -0,0 +1,36 @@
1
+ module KPI
2
+ class MergedReport
3
+ def initialize(*args, &block)
4
+ raise ArgumentError, "Should have any argument" if args.length == 0
5
+ 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
10
+ end
11
+
12
+ def entries
13
+ Enumerator.new do |yielder|
14
+ defined_kpis.each do |kpi_method|
15
+ yielder.yield(send(kpi_method))
16
+ end
17
+ end
18
+ end
19
+
20
+ def title
21
+ self.class.name
22
+ end
23
+
24
+ def defined_kpis
25
+ @reports.map(&:defined_kpis).inject(&:&)
26
+ end
27
+
28
+ 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.gsub("$$", orginal.description) : nil)
32
+
33
+ KPI::Entry.new(result.name.gsub("$$", orginal.name), result.value, :description => description)
34
+ end
35
+ end
36
+ end
@@ -1,5 +1,5 @@
1
1
  module KPI
2
- module Report
2
+ class Report
3
3
  module DynamicDefinitions
4
4
  module ClassMethods
5
5
  def method_added(name)
@@ -1,5 +1,5 @@
1
1
  module KPI
2
- module Report
2
+ class Report
3
3
  module SuppressMemoization
4
4
  def suppress_memoization
5
5
  Thread.current[:'suppress memoization'] = true
@@ -0,0 +1,41 @@
1
+ module KPI
2
+ class Report
3
+ extend KPI::Report::SuppressMemoization
4
+ extend ActiveSupport::Memoizable
5
+
6
+ include KPI::Report::DynamicDefinitions
7
+
8
+ blacklist :initialize, :collect!, :entries, :time, :title, :defined_kpis, :result
9
+
10
+ def initialize(*args)
11
+ options = args.extract_options!
12
+ @time = options[:time] || Time.now
13
+ end
14
+ attr_reader :time
15
+
16
+ def collect!
17
+ self.defined_kpis.each {|kpi_method| send(kpi_method) }
18
+ self
19
+ end
20
+
21
+ def entries
22
+ Enumerator.new do |yielder|
23
+ self.class.defined_kpis.each do |kpi_method|
24
+ yielder.yield(send(kpi_method))
25
+ end
26
+ end
27
+ end
28
+
29
+ def title
30
+ self.class.name
31
+ end
32
+
33
+ def defined_kpis
34
+ self.class.defined_kpis
35
+ end
36
+
37
+ def result(*args)
38
+ KPI::Entry.new *args
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,7 @@
1
+ module ExtractOptions
2
+ def extract_options!
3
+ last.is_a?(::Hash) ? pop : {}
4
+ end
5
+ end
6
+
7
+ Array.send(:include, ExtractOptions)
data/lib/kpi.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'array/extract_options'
2
+
1
3
  module KPI
2
4
  require 'engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
3
5
  require 'kpi/18compatibility' if RUBY_VERSION < '1.9'
data/test/test_helper.rb CHANGED
@@ -14,6 +14,6 @@ require File.join(File.dirname(__FILE__), '..', 'lib/kpi/configuration')
14
14
  require File.join(File.dirname(__FILE__), '..', 'app/models/kpi/entry')
15
15
  require File.join(File.dirname(__FILE__), '..', 'app/models/kpi/report/dynamic_definitions')
16
16
  require File.join(File.dirname(__FILE__), '..', 'app/models/kpi/report/suppress_memoization')
17
- require File.join(File.dirname(__FILE__), '..', 'app/models/kpi/report/base')
18
- require File.join(File.dirname(__FILE__), '..', 'app/models/kpi/report/merged')
17
+ require File.join(File.dirname(__FILE__), '..', 'app/models/kpi/report')
18
+ require File.join(File.dirname(__FILE__), '..', 'app/models/kpi/merged_report')
19
19
 
@@ -0,0 +1,32 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
+
3
+ describe "KPI::Entry" do
4
+ it "should require exactly 2 arguments" do
5
+ assert_raises(ArgumentError)) { KPI::Entry.new }
6
+ assert_raises(ArgumentError)) { KPI::Entry.new "test" }
7
+ assert_raises(ArgumentError)) { KPI::Entry.new "test", 1, "aaa" }
8
+ end
9
+
10
+ describe "when title and value given" do
11
+ before { @entry = KPI::Entry.new "name", "value" }
12
+
13
+ it "returns name" do
14
+ assert_equal("name", @entry.name)
15
+ end
16
+
17
+ it "returns value" do
18
+ assert_equal("value", @entry.value)
19
+ end
20
+
21
+ it "returns nil as description" do
22
+ assert_nil(@entry.description)
23
+ end
24
+ describe "when description given" do
25
+ before { @entry = KPI::Entry.new "name", "value", :description => "desc" }
26
+
27
+ it "returns description" do
28
+ assert_equal("desc", @entry.description)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,23 +1,23 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../../../test_helper')
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
2
 
3
- describe "KPI::Report::Merged" do
3
+ describe "KPI::MergedReport" do
4
4
 
5
5
  before do
6
- class TestKpi < KPI::Report::Base
6
+ class TestKpi < KPI::Report
7
7
  def initialize return_value = 1
8
8
  super()
9
9
  @return = return_value
10
10
  end
11
11
 
12
12
  def test_kpi
13
- return ["title", @return, "description"]
13
+ result "title", @return, :description => "description"
14
14
  end
15
15
 
16
16
  def test_kpi_2
17
- return ["title 2 ", @return*2]
17
+ result "title 2 ", @return*2
18
18
  end
19
19
  end
20
- class AnotherReport < KPI::Report::Base
20
+ class AnotherReport < KPI::Report
21
21
  end
22
22
  end
23
23
 
@@ -28,26 +28,26 @@ describe "KPI::Report::Merged" do
28
28
 
29
29
  describe "when initializing" do
30
30
  it "should initialize with list of KPI::Report::Base objects and block" do
31
- KPI::Report::Merged.new(TestKpi.new) {}
32
- KPI::Report::Merged.new(TestKpi.new,TestKpi.new) {}
33
- KPI::Report::Merged.new(TestKpi.new,TestKpi.new,TestKpi.new) {}
31
+ KPI::MergedReport.new(TestKpi.new) {}
32
+ KPI::MergedReport.new(TestKpi.new, TestKpi.new) {}
33
+ KPI::MergedReport.new(TestKpi.new,TestKpi.new, TestKpi.new) {}
34
34
  end
35
35
 
36
36
  it "should require at least one element when initializing" do
37
37
  assert_raises(ArgumentError) do
38
- KPI::Report::Merged.new() {}
38
+ KPI::MergedReport.new() {}
39
39
  end
40
40
  end
41
41
 
42
42
  it "should require objects of the same type when initializing" do
43
43
  assert_raises(ArgumentError) do
44
- KPI::Report::Merged.new(TestKpi.new,AnotherReport.new) {}
44
+ KPI::MergedReport.new(TestKpi.new, AnotherReport.new) {}
45
45
  end
46
46
  end
47
47
 
48
48
  it "should require block when initializing" do
49
49
  assert_raises(Exception) do
50
- KPI::Report::Merged.new(TestKpi.new)
50
+ KPI::MergedReport.new(TestKpi.new)
51
51
  end
52
52
  end
53
53
  end
@@ -57,26 +57,26 @@ describe "KPI::Report::Merged" do
57
57
  report1 = TestKpi.new(2)
58
58
  report2 = TestKpi.new(8)
59
59
 
60
- @average = KPI::Report::Merged.new(report1, report2) do |*entries|
61
- average = entries.map{|e| KPI::Entry.new(*e).value }.sum / entries.size
62
- ["Average $$", average, "$$ (average)"]
60
+ @average = KPI::MergedReport.new(report1, report2) do |*entries|
61
+ average = entries.map(&:value).sum / entries.size
62
+ KPI::Entry.new "Average $$", average, :description => "$$ (average)"
63
63
  end
64
64
  end
65
65
 
66
66
  it "should calculate value using block given in initializer when asking for KPI" do
67
- assert_equal 5, @average.test_kpi[1]
67
+ assert_equal 5, @average.test_kpi.value
68
68
  end
69
69
 
70
70
  it "should change $$ in title to indicator title" do
71
- assert_equal "Average title", @average.test_kpi[0]
71
+ assert_equal "Average title", @average.test_kpi.name
72
72
  end
73
73
 
74
74
  it "should change $$ in description to indicator descripiton" do
75
- assert_equal "description (average)", @average.test_kpi[2]
75
+ assert_equal "description (average)", @average.test_kpi.description
76
76
  end
77
77
 
78
78
  it "should return nil description when no description" do
79
- assert_nil @average.test_kpi_2[2]
79
+ assert_nil @average.test_kpi_2.description
80
80
  end
81
81
 
82
82
  describe "entries" do
@@ -96,5 +96,11 @@ describe "KPI::Report::Merged" do
96
96
  assert_equal [5,10], @average.entries.map(&:value)
97
97
  end
98
98
  end
99
+
100
+ describe :defined_kpis do
101
+ it "should return KPIs defined by all compounds" do
102
+ assert_equal TestKpi.defined_kpis, @average.defined_kpis
103
+ end
104
+ end
99
105
  end
100
106
  end
@@ -1,16 +1,17 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../../../test_helper')
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
2
 
3
- describe "KPI::Report::Base" do
3
+ describe "KPI::Report" do
4
4
  before do
5
- class TestKpi < KPI::Report::Base
5
+ class TestKpi < KPI::Report
6
6
  def test_kpi
7
- return ["title", 1, "description"]
7
+ return KPI::Entry.new "title", 1, :description => "description"
8
8
  end
9
9
 
10
10
  def another_kpi
11
- return ["another title", 0]
11
+ return KPI::Entry.new "another title", 0
12
12
  end
13
13
  end
14
+ @kpi = TestKpi.new
14
15
  end
15
16
 
16
17
  after { Object.send(:remove_const, :TestKpi) }
@@ -29,15 +30,18 @@ describe "KPI::Report::Base" do
29
30
  end
30
31
 
31
32
  describe :collect! do
32
- before { @kpi = TestKpi.new }
33
33
  it "should collect all KPIs" do
34
34
  assert_equal 2, @kpi.collect!.entries.count
35
35
  end
36
36
  end
37
+
38
+ describe :defined_kpis do
39
+ it "should return KPIs defined by class" do
40
+ assert_equal TestKpi.defined_kpis, @kpi.defined_kpis
41
+ end
42
+ end
37
43
 
38
44
  describe :entries do
39
- before { @kpi = TestKpi.new }
40
-
41
45
  it "should return enumerator" do
42
46
  assert @kpi.entries.kind_of?(Enumerable)
43
47
  end
@@ -61,7 +65,28 @@ describe "KPI::Report::Base" do
61
65
 
62
66
  describe :title do
63
67
  it "should return class name by default" do
64
- assert_equal "TestKpi", TestKpi.new.title
68
+ assert_equal "TestKpi", @kpi.title
69
+ end
70
+ end
71
+
72
+ describe :time do
73
+ it "should return overriden time" do
74
+ assert_equal(:time, TestKpi.new(:time => :time).time)
75
+ end
76
+ end
77
+
78
+ describe :result do
79
+ it "creates KPI::Entry" do
80
+ class TestKpi
81
+ def super_kpi
82
+ result "test", 2, :description => "desc"
83
+ end
84
+ end
85
+
86
+ @entry = TestKpi.new.super_kpi
87
+ assert_equal("test", @entry.name)
88
+ assert_equal(2, @entry.value)
89
+ assert_equal("desc", @entry.description)
65
90
  end
66
91
  end
67
92
  end
metadata CHANGED
@@ -1,8 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kpi
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 9
4
5
  prerelease:
5
- version: 0.5.0
6
+ segments:
7
+ - 0
8
+ - 5
9
+ - 1
10
+ version: 0.5.1
6
11
  platform: ruby
7
12
  authors:
8
13
  - Artur Roszczyk
@@ -14,71 +19,94 @@ date: 2011-05-13 00:00:00 +02:00
14
19
  default_executable:
15
20
  dependencies:
16
21
  - !ruby/object:Gem::Dependency
17
- name: actionmailer
22
+ type: :runtime
18
23
  requirement: &id001 !ruby/object:Gem::Requirement
19
24
  none: false
20
25
  requirements:
21
26
  - - ">="
22
27
  - !ruby/object:Gem::Version
28
+ hash: 5
29
+ segments:
30
+ - 2
31
+ - 3
23
32
  version: "2.3"
24
- type: :runtime
25
- prerelease: false
33
+ name: actionmailer
26
34
  version_requirements: *id001
35
+ prerelease: false
27
36
  - !ruby/object:Gem::Dependency
28
- name: activesupport
37
+ type: :runtime
29
38
  requirement: &id002 !ruby/object:Gem::Requirement
30
39
  none: false
31
40
  requirements:
32
41
  - - ">="
33
42
  - !ruby/object:Gem::Version
43
+ hash: 5
44
+ segments:
45
+ - 2
46
+ - 3
34
47
  version: "2.3"
35
- type: :runtime
36
- prerelease: false
48
+ name: activesupport
37
49
  version_requirements: *id002
50
+ prerelease: false
38
51
  - !ruby/object:Gem::Dependency
39
- name: minitest
52
+ type: :development
40
53
  requirement: &id003 !ruby/object:Gem::Requirement
41
54
  none: false
42
55
  requirements:
43
56
  - - ">="
44
57
  - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
45
61
  version: "0"
46
- type: :development
47
- prerelease: false
62
+ name: minitest
48
63
  version_requirements: *id003
64
+ prerelease: false
49
65
  - !ruby/object:Gem::Dependency
50
- name: bundler
66
+ type: :development
51
67
  requirement: &id004 !ruby/object:Gem::Requirement
52
68
  none: false
53
69
  requirements:
54
70
  - - ~>
55
71
  - !ruby/object:Gem::Version
72
+ hash: 15
73
+ segments:
74
+ - 1
75
+ - 0
56
76
  version: "1.0"
57
- type: :development
58
- prerelease: false
77
+ name: bundler
59
78
  version_requirements: *id004
79
+ prerelease: false
60
80
  - !ruby/object:Gem::Dependency
61
- name: jeweler
81
+ type: :development
62
82
  requirement: &id005 !ruby/object:Gem::Requirement
63
83
  none: false
64
84
  requirements:
65
85
  - - ~>
66
86
  - !ruby/object:Gem::Version
87
+ hash: 7
88
+ segments:
89
+ - 1
90
+ - 5
91
+ - 2
67
92
  version: 1.5.2
68
- type: :development
69
- prerelease: false
93
+ name: jeweler
70
94
  version_requirements: *id005
95
+ prerelease: false
71
96
  - !ruby/object:Gem::Dependency
72
- name: rcov
97
+ type: :development
73
98
  requirement: &id006 !ruby/object:Gem::Requirement
74
99
  none: false
75
100
  requirements:
76
101
  - - ">="
77
102
  - !ruby/object:Gem::Version
103
+ hash: 3
104
+ segments:
105
+ - 0
78
106
  version: "0"
79
- type: :development
80
- prerelease: false
107
+ name: rcov
81
108
  version_requirements: *id006
109
+ prerelease: false
82
110
  description: This gem helps you to track key indicators in your Rails app.
83
111
  email: artur.roszczyk@gmail.com
84
112
  executables: []
@@ -90,10 +118,11 @@ extra_rdoc_files:
90
118
  - README.rdoc
91
119
  files:
92
120
  - app/models/kpi/entry.rb
93
- - app/models/kpi/report/base.rb
121
+ - app/models/kpi/merged_report.rb
122
+ - app/models/kpi/report.rb
94
123
  - app/models/kpi/report/dynamic_definitions.rb
95
- - app/models/kpi/report/merged.rb
96
124
  - app/models/kpi/report/suppress_memoization.rb
125
+ - lib/array/extract_options.rb
97
126
  - lib/engine.rb
98
127
  - lib/generators/kpi/USAGE
99
128
  - lib/generators/kpi/kpi_generator.rb
@@ -103,8 +132,9 @@ files:
103
132
  - LICENSE.txt
104
133
  - README.rdoc
105
134
  - test/test_helper.rb
106
- - test/unit/kpi/report/base_test.rb
107
- - test/unit/kpi/report/merged_test.rb
135
+ - test/unit/kpi/entry_tesr.rb
136
+ - test/unit/kpi/merged_report_test.rb
137
+ - test/unit/kpi/report_test.rb
108
138
  has_rdoc: true
109
139
  homepage: http://github.com/sevos/kpi
110
140
  licenses:
@@ -119,7 +149,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
119
149
  requirements:
120
150
  - - ">="
121
151
  - !ruby/object:Gem::Version
122
- hash: -2742020933560976689
152
+ hash: 3
123
153
  segments:
124
154
  - 0
125
155
  version: "0"
@@ -128,15 +158,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
128
158
  requirements:
129
159
  - - ">="
130
160
  - !ruby/object:Gem::Version
161
+ hash: 3
162
+ segments:
163
+ - 0
131
164
  version: "0"
132
165
  requirements: []
133
166
 
134
167
  rubyforge_project:
135
- rubygems_version: 1.5.2
168
+ rubygems_version: 1.6.2
136
169
  signing_key:
137
170
  specification_version: 3
138
171
  summary: Key Performance Indicators for Rails 3.x
139
172
  test_files:
140
173
  - test/test_helper.rb
141
- - test/unit/kpi/report/base_test.rb
142
- - test/unit/kpi/report/merged_test.rb
174
+ - test/unit/kpi/entry_tesr.rb
175
+ - test/unit/kpi/merged_report_test.rb
176
+ - test/unit/kpi/report_test.rb
@@ -1,35 +0,0 @@
1
- module KPI
2
- module Report
3
- class Base
4
- extend KPI::Report::SuppressMemoization
5
- extend ActiveSupport::Memoizable
6
-
7
- include KPI::Report::DynamicDefinitions
8
-
9
- blacklist :initialize, :collect!, :entries, :time, :title
10
-
11
- def initialize(time=Time.now)
12
- @time = time
13
- end
14
- attr_reader :time
15
-
16
- def collect!
17
- self.class.defined_kpis.each {|kpi_method| send(kpi_method) }
18
- self
19
- end
20
-
21
- def entries
22
- Enumerator.new do |yielder|
23
- self.class.defined_kpis.each do |kpi_method|
24
- result = send(kpi_method)
25
- yielder.yield(Entry.new(*result))
26
- end
27
- end
28
- end
29
-
30
- def title
31
- self.class.name
32
- end
33
- end
34
- end
35
- end
@@ -1,38 +0,0 @@
1
- module KPI
2
- module Report
3
- class Merged
4
- def initialize(*args, &block)
5
- raise ArgumentError, "Should have any argument" if args.length == 0
6
- raise Exception unless block_given?
7
- raise ArgumentError, "Argument must be the same type" unless args.map(&:class).uniq.size == 1
8
-
9
- @reports ||= args
10
- @compare = block
11
- end
12
-
13
- def entries
14
- Enumerator.new do |yielder|
15
- @reports.first.class.defined_kpis.each do |kpi_method|
16
- result = self.send(kpi_method.to_sym)
17
- yielder.yield(KPI::Entry.new(*result))
18
- end
19
- end
20
- end
21
-
22
- def title
23
- self.class.name
24
- end
25
-
26
- def method_missing(name, *args)
27
- result = @compare.call(*@reports.map(&name.to_sym))
28
- [0,2].each do |i|
29
- text = @reports.first.send(name.to_sym)[i]
30
- result[i] = text ? result[i].gsub!("$$", text) : nil
31
- end
32
- result
33
- end
34
-
35
-
36
- end
37
- end
38
- end