descendants_tracker 0.0.1 → 0.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.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +5 -0
  3. data/.ruby-gemset +1 -0
  4. data/.travis.yml +24 -13
  5. data/CONTRIBUTING.md +10 -0
  6. data/Gemfile +3 -51
  7. data/Gemfile.devtools +71 -0
  8. data/LICENSE +2 -1
  9. data/README.md +22 -64
  10. data/Rakefile +2 -6
  11. data/config/devtools.yml +4 -0
  12. data/config/flay.yml +2 -2
  13. data/config/flog.yml +1 -1
  14. data/config/mutant.yml +3 -0
  15. data/config/{site.reek → reek.yml} +64 -49
  16. data/config/rubocop.yml +62 -0
  17. data/descendants_tracker.gemspec +8 -6
  18. data/lib/descendants_tracker/version.rb +7 -2
  19. data/lib/descendants_tracker.rb +30 -6
  20. data/spec/spec_helper.rb +25 -6
  21. data/spec/support/config_alias.rb +2 -0
  22. data/spec/unit/descendants_tracker/add_descendant_spec.rb +11 -9
  23. data/spec/unit/descendants_tracker/descendants_spec.rb +4 -2
  24. data/spec/unit/descendants_tracker/inherited_spec.rb +26 -0
  25. metadata +75 -91
  26. data/.rvmrc +0 -1
  27. data/config/roodi.yml +0 -18
  28. data/spec/shared/command_method_behavior.rb +0 -7
  29. data/spec/shared/each_method_behaviour.rb +0 -15
  30. data/spec/shared/hash_method_behavior.rb +0 -17
  31. data/spec/shared/idempotent_method_behavior.rb +0 -7
  32. data/spec/shared/invertible_method_behaviour.rb +0 -9
  33. data/tasks/metrics/ci.rake +0 -9
  34. data/tasks/metrics/flay.rake +0 -45
  35. data/tasks/metrics/flog.rake +0 -49
  36. data/tasks/metrics/heckle.rake +0 -208
  37. data/tasks/metrics/metric_fu.rake +0 -31
  38. data/tasks/metrics/reek.rake +0 -21
  39. data/tasks/metrics/roodi.rake +0 -19
  40. data/tasks/metrics/yardstick.rake +0 -25
  41. data/tasks/spec.rake +0 -60
  42. data/tasks/yard.rake +0 -11
@@ -1,13 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ require 'thread_safe'
4
+
1
5
  # Module that adds descendant tracking to a class
2
6
  module DescendantsTracker
3
7
 
4
8
  # Return the descendants of this class
5
9
  #
6
- # @return [Array<Class>]
10
+ # @example
11
+ # descendants = ParentClass.descendants
12
+ #
13
+ # @return [Array<Class<DescendantsTracker>>]
14
+ #
15
+ # @api public
16
+ attr_reader :descendants
17
+
18
+ # Setup the class for descendant tracking
19
+ #
20
+ # @param [Class<DescendantsTracker>] descendant
21
+ #
22
+ # @return [undefined]
7
23
  #
8
24
  # @api private
9
- def descendants
10
- @descendants ||= []
25
+ def self.setup(descendant)
26
+ descendant.instance_variable_set(:@descendants, ThreadSafe::Array.new)
27
+ end
28
+
29
+ class << self
30
+ alias_method :extended, :setup
31
+ private :extended
11
32
  end
12
33
 
13
34
  # Add the descendant to this class and the superclass
@@ -18,8 +39,10 @@ module DescendantsTracker
18
39
  #
19
40
  # @api private
20
41
  def add_descendant(descendant)
21
- superclass = self.superclass
22
- superclass.add_descendant(descendant) if superclass.respond_to?(:add_descendant)
42
+ ancestor = superclass
43
+ if ancestor.respond_to?(:add_descendant)
44
+ ancestor.add_descendant(descendant)
45
+ end
23
46
  descendants.unshift(descendant)
24
47
  self
25
48
  end
@@ -30,11 +53,12 @@ private
30
53
  #
31
54
  # @param [Class] descendant
32
55
  #
33
- # @return [undefined]
56
+ # @return [self]
34
57
  #
35
58
  # @api private
36
59
  def inherited(descendant)
37
60
  super
61
+ DescendantsTracker.setup(descendant)
38
62
  add_descendant(descendant)
39
63
  end
40
64
 
data/spec/spec_helper.rb CHANGED
@@ -1,11 +1,30 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'descendants_tracker'
4
- require 'spec'
5
- require 'spec/autorun'
3
+ if ENV['COVERAGE'] == 'true'
4
+ require 'simplecov'
5
+ require 'coveralls'
6
+
7
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
8
+ SimpleCov::Formatter::HTMLFormatter,
9
+ Coveralls::SimpleCov::Formatter
10
+ ]
11
+
12
+ SimpleCov.start do
13
+ command_name 'spec:unit'
14
+
15
+ add_filter 'config'
16
+ add_filter 'spec'
17
+ add_filter 'vendor'
6
18
 
7
- # require spec support files and shared behavior
8
- Dir[File.expand_path('../{support,shared}/**/*.rb', __FILE__)].each { |f| require f }
19
+ minimum_coverage 100
20
+ end
21
+ end
22
+
23
+ require 'devtools/spec_helper'
24
+ require 'descendants_tracker'
9
25
 
10
- Spec::Runner.configure do |config|
26
+ RSpec.configure do |config|
27
+ config.expect_with :rspec do |expect_with|
28
+ expect_with.syntax = :expect
29
+ end
11
30
  end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'rbconfig'
2
4
 
3
5
  ::Config = RbConfig unless defined?(::Config)
@@ -1,24 +1,26 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe DescendantsTracker, '#add_descendant' do
4
6
  subject { object.add_descendant(descendant) }
5
7
 
6
8
  let(:described_class) { Class.new { extend DescendantsTracker } }
7
- let(:object) { Class.new(described_class) }
8
- let(:descendant) { Class.new }
9
+ let(:object) { Class.new(described_class) }
10
+ let(:descendant) { Class.new }
9
11
 
10
- it { should equal(object) }
12
+ it_should_behave_like 'a command method'
11
13
 
12
14
  it 'prepends the class to the descendants' do
13
15
  object.descendants << original = Class.new
14
- expect { subject }.to change { object.descendants.dup }.
15
- from([ original ]).
16
- to([ descendant, original ])
16
+ expect { subject }.to change { object.descendants.dup }
17
+ .from([original])
18
+ .to([descendant, original])
17
19
  end
18
20
 
19
21
  it 'prepends the class to the superclass descendants' do
20
- expect { subject }.to change { object.superclass.descendants.dup }.
21
- from([ object ]).
22
- to([ descendant, object ])
22
+ expect { subject }.to change { object.superclass.descendants.dup }
23
+ .from([object])
24
+ .to([descendant, object])
23
25
  end
24
26
  end
@@ -1,10 +1,12 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe DescendantsTracker, '#descendants' do
4
6
  subject { object.descendants }
5
7
 
6
8
  let(:described_class) { Class.new { extend DescendantsTracker } }
7
- let(:object) { described_class }
9
+ let(:object) { described_class }
8
10
 
9
11
  context 'when there are no descendants' do
10
12
  it_should_behave_like 'an idempotent method'
@@ -17,6 +19,6 @@ describe DescendantsTracker, '#descendants' do
17
19
 
18
20
  it_should_behave_like 'an idempotent method'
19
21
 
20
- it { should eql([ descendant ]) }
22
+ it { should eql([descendant]) }
21
23
  end
22
24
  end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe DescendantsTracker, '#inherited' do
6
+ subject { Class.new(object) }
7
+
8
+ let!(:object) { Class.new(superklass).extend(self.class.described_class) }
9
+ let(:superklass) { Class.new }
10
+
11
+ it 'delegates to the superclass #inherited method' do
12
+ superklass.should_receive(:inherited) do |descendant|
13
+ expect(descendant).to be_instance_of(Class)
14
+ expect(descendant.ancestors).to include(object)
15
+ end
16
+ subject
17
+ end
18
+
19
+ it 'adds the descendant' do
20
+ expect(object.descendants).to include(subject)
21
+ end
22
+
23
+ it 'sets up descendants in the child class' do
24
+ expect(subject.descendants).to eql([])
25
+ end
26
+ end
metadata CHANGED
@@ -1,141 +1,125 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: descendants_tracker
3
- version: !ruby/object:Gem::Version
4
- hash: 29
5
- prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 1
10
- version: 0.0.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Dan Kubb
14
8
  - Piotr Solnica
15
9
  - Markus Schirp
16
10
  autorequire:
17
11
  bindir: bin
18
12
  cert_chain: []
19
-
20
- date: 2012-11-24 00:00:00 Z
21
- dependencies:
22
- - !ruby/object:Gem::Dependency
23
- name: rake
13
+ date: 2014-03-27 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: thread_safe
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '0.3'
22
+ - - '>='
23
+ - !ruby/object:Gem::Version
24
+ version: 0.3.1
25
+ type: :runtime
24
26
  prerelease: false
25
- requirement: &id001 !ruby/object:Gem::Requirement
26
- none: false
27
- requirements:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ~>
30
+ - !ruby/object:Gem::Version
31
+ version: '0.3'
32
+ - - '>='
33
+ - !ruby/object:Gem::Version
34
+ version: 0.3.1
35
+ - !ruby/object:Gem::Dependency
36
+ name: bundler
37
+ requirement: !ruby/object:Gem::Requirement
38
+ requirements:
28
39
  - - ~>
29
- - !ruby/object:Gem::Version
30
- hash: 75
31
- segments:
32
- - 10
33
- - 0
34
- - 2
35
- version: 10.0.2
40
+ - !ruby/object:Gem::Version
41
+ version: '1.5'
42
+ - - '>='
43
+ - !ruby/object:Gem::Version
44
+ version: 1.5.3
36
45
  type: :development
37
- version_requirements: *id001
38
- - !ruby/object:Gem::Dependency
39
- name: rspec
40
46
  prerelease: false
41
- requirement: &id002 !ruby/object:Gem::Requirement
42
- none: false
43
- requirements:
47
+ version_requirements: !ruby/object:Gem::Requirement
48
+ requirements:
44
49
  - - ~>
45
- - !ruby/object:Gem::Version
46
- hash: 31
47
- segments:
48
- - 1
49
- - 3
50
- - 2
51
- version: 1.3.2
52
- type: :development
53
- version_requirements: *id002
50
+ - !ruby/object:Gem::Version
51
+ version: '1.5'
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.5.3
54
55
  description: Module that adds descendant tracking to a class
55
- email:
56
+ email:
56
57
  - dan.kubb@gmail.com
57
58
  - piotr.solnica@gmail.com
58
- - mbj@seonic.net
59
+ - mbj@schirp-dso.com
59
60
  executables: []
60
-
61
61
  extensions: []
62
-
63
- extra_rdoc_files:
62
+ extra_rdoc_files:
64
63
  - LICENSE
65
64
  - README.md
65
+ - CONTRIBUTING.md
66
66
  - TODO
67
- files:
67
+ files:
68
68
  - .gitignore
69
- - .rvmrc
69
+ - .rspec
70
+ - .ruby-gemset
70
71
  - .travis.yml
72
+ - CONTRIBUTING.md
71
73
  - Gemfile
74
+ - Gemfile.devtools
72
75
  - Guardfile
73
76
  - LICENSE
74
77
  - README.md
75
78
  - Rakefile
76
79
  - TODO
80
+ - config/devtools.yml
77
81
  - config/flay.yml
78
82
  - config/flog.yml
79
- - config/roodi.yml
80
- - config/site.reek
83
+ - config/mutant.yml
84
+ - config/reek.yml
85
+ - config/rubocop.yml
81
86
  - config/yardstick.yml
82
87
  - descendants_tracker.gemspec
83
88
  - lib/descendants_tracker.rb
84
89
  - lib/descendants_tracker/version.rb
85
90
  - spec/rcov.opts
86
- - spec/shared/command_method_behavior.rb
87
- - spec/shared/each_method_behaviour.rb
88
- - spec/shared/hash_method_behavior.rb
89
- - spec/shared/idempotent_method_behavior.rb
90
- - spec/shared/invertible_method_behaviour.rb
91
91
  - spec/spec.opts
92
92
  - spec/spec_helper.rb
93
93
  - spec/support/config_alias.rb
94
94
  - spec/unit/descendants_tracker/add_descendant_spec.rb
95
95
  - spec/unit/descendants_tracker/descendants_spec.rb
96
- - tasks/metrics/ci.rake
97
- - tasks/metrics/flay.rake
98
- - tasks/metrics/flog.rake
99
- - tasks/metrics/heckle.rake
100
- - tasks/metrics/metric_fu.rake
101
- - tasks/metrics/reek.rake
102
- - tasks/metrics/roodi.rake
103
- - tasks/metrics/yardstick.rake
104
- - tasks/spec.rake
105
- - tasks/yard.rake
96
+ - spec/unit/descendants_tracker/inherited_spec.rb
106
97
  homepage: https://github.com/dkubb/descendants_tracker
107
- licenses: []
108
-
98
+ licenses:
99
+ - MIT
100
+ metadata: {}
109
101
  post_install_message:
110
102
  rdoc_options: []
111
-
112
- require_paths:
103
+ require_paths:
113
104
  - lib
114
- required_ruby_version: !ruby/object:Gem::Requirement
115
- none: false
116
- requirements:
117
- - - ">="
118
- - !ruby/object:Gem::Version
119
- hash: 3
120
- segments:
121
- - 0
122
- version: "0"
123
- required_rubygems_version: !ruby/object:Gem::Requirement
124
- none: false
125
- requirements:
126
- - - ">="
127
- - !ruby/object:Gem::Version
128
- hash: 3
129
- segments:
130
- - 0
131
- version: "0"
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
132
115
  requirements: []
133
-
134
116
  rubyforge_project:
135
- rubygems_version: 1.8.24
117
+ rubygems_version: 2.2.2
136
118
  signing_key:
137
- specification_version: 3
119
+ specification_version: 4
138
120
  summary: Module that adds descendant tracking to a class
139
- test_files: []
140
-
121
+ test_files:
122
+ - spec/unit/descendants_tracker/add_descendant_spec.rb
123
+ - spec/unit/descendants_tracker/descendants_spec.rb
124
+ - spec/unit/descendants_tracker/inherited_spec.rb
141
125
  has_rdoc:
data/.rvmrc DELETED
@@ -1 +0,0 @@
1
- rvm use @$(basename `pwd`) --create
data/config/roodi.yml DELETED
@@ -1,18 +0,0 @@
1
- ---
2
- AbcMetricMethodCheck: { score: 10.3 }
3
- AssignmentInConditionalCheck: { }
4
- CaseMissingElseCheck: { }
5
- ClassLineCountCheck: { line_count: 293 }
6
- ClassNameCheck: { pattern: !ruby/regexp '/\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/' }
7
- ClassVariableCheck: { }
8
- CyclomaticComplexityBlockCheck: { complexity: 2 }
9
- CyclomaticComplexityMethodCheck: { complexity: 4 }
10
- EmptyRescueBodyCheck: { }
11
- ForLoopCheck: { }
12
- # TODO: decrease line_count to 5 to 10
13
- MethodLineCountCheck: { line_count: 14 }
14
- MethodNameCheck: { pattern: !ruby/regexp '/\A(?:[a-z\d](?:_?[a-z\d])+[?!=]?|\[\]=?|==|<=>|[+*&|-])\z/' }
15
- ModuleLineCountCheck: { line_count: 295 }
16
- ModuleNameCheck: { pattern: !ruby/regexp '/\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/' }
17
- # TODO: decrease parameter_count to 2 or less
18
- ParameterNumberCheck: { parameter_count: 3 }
@@ -1,7 +0,0 @@
1
- # encoding: utf-8
2
-
3
- shared_examples_for 'a command method' do
4
- it 'returns self' do
5
- should equal(object)
6
- end
7
- end
@@ -1,15 +0,0 @@
1
- # encoding: utf-8
2
-
3
- shared_examples_for 'an #each method' do
4
- it_should_behave_like 'a command method'
5
-
6
- context 'with no block' do
7
- subject { object.each }
8
-
9
- it { should be_instance_of(to_enum.class) }
10
-
11
- it 'yields the expected values' do
12
- subject.to_a.should eql(object.to_a)
13
- end
14
- end
15
- end
@@ -1,17 +0,0 @@
1
- # encoding: utf-8
2
-
3
- shared_examples_for 'a hash method' do
4
- it_should_behave_like 'an idempotent method'
5
-
6
- specification = proc do
7
- should be_instance_of(Fixnum)
8
- end
9
-
10
- it 'is a fixnum' do
11
- instance_eval(&specification)
12
- end
13
-
14
- it 'memoizes the hash code' do
15
- subject.should eql(object.memoized(:hash))
16
- end
17
- end
@@ -1,7 +0,0 @@
1
- # encoding: utf-8
2
-
3
- shared_examples_for 'an idempotent method' do
4
- it 'is idempotent' do
5
- should equal(instance_eval(&self.class.subject))
6
- end
7
- end
@@ -1,9 +0,0 @@
1
- # encoding: utf-8
2
-
3
- shared_examples_for 'an invertible method' do
4
- it_should_behave_like 'an idempotent method'
5
-
6
- it 'is invertible' do
7
- subject.inverse.should equal(object)
8
- end
9
- end
@@ -1,9 +0,0 @@
1
- # encoding: utf-8
2
-
3
- desc 'Run metrics with Heckle'
4
- task :ci => %w[ ci:metrics metrics:heckle ]
5
-
6
- namespace :ci do
7
- desc 'Run metrics (except heckle) and spec'
8
- task :metrics => %w[ spec metrics:verify_measurements metrics:flog metrics:flay metrics:reek metrics:roodi metrics:all ]
9
- end
@@ -1,45 +0,0 @@
1
- # encoding: utf-8
2
-
3
- begin
4
- require 'flay'
5
- require 'yaml'
6
-
7
- config = YAML.load_file(File.expand_path('../../../config/flay.yml', __FILE__)).freeze
8
- threshold = config.fetch('threshold').to_i
9
- total_score = config.fetch('total_score').to_f
10
- files = Flay.expand_dirs_to_files(config.fetch('path', 'lib')).sort
11
-
12
- namespace :metrics do
13
- # original code by Marty Andrews:
14
- # http://blog.martyandrews.net/2009/05/enforcing-ruby-code-quality.html
15
- desc 'Analyze for code duplication'
16
- task :flay do
17
- # run flay once without a threshold to ensure the max mass matches the threshold
18
- flay = Flay.new(:fuzzy => false, :verbose => false, :mass => 0)
19
- flay.process(*files)
20
-
21
- max = (flay.masses.map { |hash, mass| mass.to_f / flay.hashes[hash].size }.max) || 0
22
- unless max >= threshold
23
- raise "Adjust flay threshold down to #{max}"
24
- end
25
-
26
- total = flay.masses.reduce(0.0) { |total, (hash, mass)| total + (mass.to_f / flay.hashes[hash].size) }
27
- unless total == total_score
28
- raise "Flay total is now #{total}, but expected #{total_score}"
29
- end
30
-
31
- # run flay a second time with the threshold set
32
- flay = Flay.new(:fuzzy => false, :verbose => false, :mass => threshold.succ)
33
- flay.process(*files)
34
-
35
- if flay.masses.any?
36
- flay.report
37
- raise "#{flay.masses.size} chunks of code have a duplicate mass > #{threshold}"
38
- end
39
- end
40
- end
41
- rescue LoadError
42
- task :flay do
43
- $stderr.puts 'Flay is not available. In order to run flay, you must: gem install flay'
44
- end
45
- end
@@ -1,49 +0,0 @@
1
- # encoding: utf-8
2
-
3
- begin
4
- require 'flog'
5
- require 'yaml'
6
-
7
- class Float
8
- def round_to(n)
9
- (self * 10**n).round.to_f * 10**-n
10
- end
11
- end
12
-
13
- config = YAML.load_file(File.expand_path('../../../config/flog.yml', __FILE__)).freeze
14
- threshold = config.fetch('threshold').to_f.round_to(1)
15
-
16
- namespace :metrics do
17
- # original code by Marty Andrews:
18
- # http://blog.martyandrews.net/2009/05/enforcing-ruby-code-quality.html
19
- desc 'Analyze for code complexity'
20
- task :flog do
21
- flog = Flog.new
22
- flog.flog Array(config.fetch('path', 'lib'))
23
-
24
- totals = flog.totals.select { |name, score| name[-5, 5] != '#none' }.
25
- map { |name, score| [ name, score.round_to(1) ] }.
26
- sort_by { |name, score| score }
27
-
28
- if totals.any?
29
- max = totals.last[1]
30
- unless max >= threshold
31
- raise "Adjust flog score down to #{max}"
32
- end
33
- end
34
-
35
- bad_methods = totals.select { |name, score| score > threshold }
36
- if bad_methods.any?
37
- bad_methods.reverse_each do |name, score|
38
- puts '%8.1f: %s' % [ score, name ]
39
- end
40
-
41
- raise "#{bad_methods.size} methods have a flog complexity > #{threshold}"
42
- end
43
- end
44
- end
45
- rescue LoadError
46
- task :flog do
47
- $stderr.puts 'Flog is not available. In order to run flog, you must: gem install flog'
48
- end
49
- end