descendants-loader 0.0.3 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 5a4da25288b46378e4bd0f2586c0feeeb67c7d18
4
- data.tar.gz: ccba8c77dab22aa017571f75705874d7fe5bf5a0
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ N2Y2Y2QyYTAxODA0YzZkMjc4NjI1NzliOTdjZjc4ZDg3MDZhMTA1NA==
5
+ data.tar.gz: !binary |-
6
+ ZmQ3NjM4MDZiMzkxM2FkMTA3MmRjZGQ3OGIxMjIyM2VmYmI5ZWZiMQ==
5
7
  SHA512:
6
- metadata.gz: 6c6498507b94299517fdb85ab247990eec340a60fef3795f81c76595a9fc8e6d0050f60d694a6055f254228797ef9a1899845f1940ca624f9f8ae2122aff2050
7
- data.tar.gz: 04e0e173ae6674e3246aa81adc8288ca9f8388a96c458edc912484cb9a4b1972181a5db89fa66ac838939bec14074bc127021a6947deb22be224f90e12cc04a5
8
+ metadata.gz: !binary |-
9
+ MjE4Yjc4MzgwMjhiZTgyYmQ4MDk0ZWFiNjQyOGExY2EyNGUzZDU5YmE2ODhj
10
+ MjkyNGM3Y2M2MGY1YjhhYjU3OTVkYTlkYTI5YjRkODljNjVmNjY4NDU1ZmJj
11
+ NzgxMTEwZjQ2MTAxODgzNWMzZjFhNTdlMWE3OTlhYjY5YzFhYjY=
12
+ data.tar.gz: !binary |-
13
+ ZWM3ZTM0M2QyMDIyZWMyNTAyZGQyNGQ5NDQ5NjBjNTc0YmQ4YTc5NzU0NmY0
14
+ OWY2Zjc5ZWYzY2Q0MTYwMmMwOTI3MGJiNzk2OTMyYTc5YmRjMjNjZWE2ODM4
15
+ Y2JjM2M1MDgyYjgwNWQ0YzNiMGRlYjYxNGFkMjRjNjBlN2ZmODI=
@@ -1,16 +1,36 @@
1
1
  require 'active_support/core_ext/string/inflections'
2
+ require 'active_support/core_ext/class/subclasses'
2
3
 
3
4
  path = File.expand_path(File.dirname(__FILE__))
4
5
  Dir["#{path}/descendants_loader/**/*.rb"].each do |file|
5
6
  require file
6
7
  end
7
8
 
9
+ #
10
+ # Descendants loader. Please check out README for a full introduction.
11
+ #
8
12
  module DescendantsLoader
13
+ #
14
+ # If the module is included it is forced to be extended.
15
+ # Usage:
16
+ # require 'descendants_loader'
17
+ # class MyClass
18
+ # include DescendantsLoader
19
+ #
20
+ # ...
21
+ # end
22
+ #
9
23
  def self.included(base)
10
24
  base.extend(ClassMethods)
11
25
  end
12
26
 
27
+ #
28
+ # Definition of class methods.
29
+ #
13
30
  module ClassMethods
31
+ #
32
+ # Overwrites Object.descendants injecting an autoload process.
33
+ #
14
34
  def descendants
15
35
  if (classes = super).empty?
16
36
  load_self_descendants
@@ -20,6 +40,9 @@ module DescendantsLoader
20
40
  classes
21
41
  end
22
42
 
43
+ #
44
+ # Overwrites Object.subclasses injecting an autoload process.
45
+ #
23
46
  def subclasses
24
47
  if (classes = super).empty?
25
48
  load_self_descendants
@@ -29,6 +52,15 @@ module DescendantsLoader
29
52
  classes
30
53
  end
31
54
 
55
+ private
56
+
57
+ #
58
+ # Find and load all ruby files under the same directory structure
59
+ # of the declared class which is including DescendantsLoader module.
60
+ #
61
+ # This is the trick to put the classes into ObjectSpace and have the
62
+ # desired behavior of Object.descendants and Object.subclasses.
63
+ #
32
64
  def load_self_descendants
33
65
  file = ClassFinder.where_is(self)
34
66
  path = File.expand_path(File.dirname(file))
@@ -12,14 +12,7 @@ module DescendantsLoader
12
12
  def class_name_from_path(path)
13
13
  ary = path.split('/')
14
14
  ary.map! { |s| s.gsub(/\.rb/, '') }
15
-
16
- index = ary.index('models') ||
17
- ary.index('workers') ||
18
- ary.index('helpers') ||
19
- ary.index('controllers') ||
20
- ary.index('mailers') ||
21
- ary.index('lib')
22
- ary.slice!(0, index + 1)
15
+ ary.slice!(0, index_of_base_dir(ary) + 1)
23
16
 
24
17
  ary.map(&:camelize).join('::')
25
18
  end
@@ -53,6 +46,16 @@ module DescendantsLoader
53
46
  def class_and_source_eq?(klass, file)
54
47
  class_name_from_path(file) == klass.to_s
55
48
  end
49
+
50
+ def index_of_base_dir(path_array)
51
+ base_dirs = %w(lib models workers schedulers controllers mailers)
52
+ index = base_dirs.map { |dir| path_array.index(dir) }.compact.first
53
+
54
+ fail ArgumentError, 'Not a valid file path. Expect to ' \
55
+ 'have a base known directory.' if index.nil?
56
+
57
+ index
58
+ end
56
59
  end
57
60
  end
58
61
  end
@@ -1,3 +1,3 @@
1
1
  module DescendantsLoader
2
- VERSION = '0.0.3'
2
+ VERSION = '0.0.4'
3
3
  end
@@ -0,0 +1,56 @@
1
+ module DescendantsLoader
2
+ describe ClassFinder do
3
+ subject { ClassFinder }
4
+
5
+ describe '.where_is' do
6
+ it 'returns ClassFinder file path' do
7
+ file_path = File.expand_path(__FILE__)
8
+ .gsub(/\/spec/, '/lib')
9
+ .gsub(/_spec/, '')
10
+
11
+ expect(subject.where_is(ClassFinder)).to eq(file_path)
12
+ end
13
+
14
+ it 'returns nil if the class does not exists in project file tree' do
15
+ expect(subject.where_is(ArgumentError)).to be_nil
16
+ end
17
+ end
18
+
19
+ describe '.class_name_from_path' do
20
+ let(:base_path) { '/a/b/c/prj' }
21
+
22
+ it 'fails if there is no mapped dirs in the given path' do
23
+ expect do
24
+ subject.class_name_from_path(base_path)
25
+ end.to raise_error(ArgumentError)
26
+ end
27
+
28
+ %w(lib models workers schedulers controllers mailers).each do |dir|
29
+ let(:path) { [base_path, dir, ''].join('/') }
30
+
31
+ it "returns not nil for #{dir}" do
32
+ expect(subject.class_name_from_path(path)).not_to be_nil
33
+ end
34
+
35
+ it "returns camelized single name in #{dir}" do
36
+ file_path = path + 'classname.rb'
37
+
38
+ expect(subject.class_name_from_path(file_path)).to eq('Classname')
39
+ end
40
+
41
+ it "returns camelized composed name #{dir}" do
42
+ file_path = path + 'class_name.rb'
43
+
44
+ expect(subject.class_name_from_path(file_path)).to eq('ClassName')
45
+ end
46
+
47
+ it "returns camelized composed name with modules in #{dir}" do
48
+ file_path = path + 'module_a/module_b/class_name.rb'
49
+ class_name = 'ModuleA::ModuleB::ClassName'
50
+
51
+ expect(subject.class_name_from_path(file_path)).to eq(class_name)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,36 @@
1
+ describe DescendantsLoader do
2
+ examples_path = "#{File.expand_path(File.dirname(__FILE__))}/examples"
3
+ context 'dumb' do
4
+ require "#{examples_path}/dumb/lib/dumb_base.rb"
5
+
6
+ describe '.descendants' do
7
+ it 'cannot find inherited classes' do
8
+ expect(DumbBase.descendants).to be_empty
9
+ end
10
+ end
11
+
12
+ describe '.subclasses' do
13
+ it 'cannot find inherited classes' do
14
+ expect(DumbBase.subclasses).to be_empty
15
+ end
16
+ end
17
+ end
18
+
19
+ context 'smart' do
20
+ require "#{examples_path}/smart/lib/smart_base.rb"
21
+
22
+ describe '.descendants' do
23
+ it 'finds SonA, SonB and SonC' do
24
+ sons = %w(SmartSonA SmartSonB SmartSonC)
25
+ expect(SmartBase.descendants.map(&:to_s)).to match_array(sons)
26
+ end
27
+ end
28
+
29
+ describe '.subclasses' do
30
+ it 'finds SonA and SonB' do
31
+ sons = %w(SmartSonA SmartSonB)
32
+ expect(SmartBase.subclasses.map(&:to_s)).to match_array(sons)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,5 @@
1
+ class DumbBase
2
+ def my_method
3
+ nil
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class DumbSon < DumbBase
2
+ def my_method
3
+ nil
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ class SmartBase
2
+ include DescendantsLoader
3
+
4
+ def my_method
5
+ nil
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ class SmartSonA < SmartBase
2
+ def my_method
3
+ nil
4
+ end
5
+ end
6
+
7
+ class SmartSonB < SmartBase
8
+ def my_method
9
+ nil
10
+ end
11
+ end
12
+
13
+ class SmartSonC < SmartSonA
14
+ def my_method
15
+ nil
16
+ end
17
+ end
@@ -5,7 +5,7 @@ SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
5
5
  SimpleCov.start do
6
6
  `git checkout origin/master coverage/.last_run.json`
7
7
 
8
- minimum_coverage(45)
8
+ minimum_coverage(96)
9
9
  maximum_coverage_drop(2)
10
10
 
11
11
  add_filter 'spec/'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: descendants-loader
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Silvestre
@@ -14,73 +14,73 @@ dependencies:
14
14
  name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - ! '>='
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '10.0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - ! '>='
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '10.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '3.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '3.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: simplecov
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - ~>
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '0.7'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - ~>
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '0.7'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: simplecov-rcov
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '0.2'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - ~>
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: '0.2'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: activesupport
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - ! '>='
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: '3.2'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - ! '>='
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
83
- description: "\n This gem is an Object.descendants and Object.subclasses loader.\n
82
+ version: '3.2'
83
+ description: ! "\n This gem is an Object.descendants and Object.subclasses loader.\n
84
84
  \ The desired classes will have an autoload of its hierarchy.\n This aims a
85
85
  problem with lazy loading ruby classes (usually under\n development environment).
86
86
  For more information please check README.\n "
@@ -93,6 +93,12 @@ files:
93
93
  - lib/descendants_loader.rb
94
94
  - lib/descendants_loader/class_finder.rb
95
95
  - lib/descendants_loader/version.rb
96
+ - spec/descendants_loader/class_finder_spec.rb
97
+ - spec/descendants_loader_spec.rb
98
+ - spec/examples/dumb/lib/dumb_base.rb
99
+ - spec/examples/dumb/lib/dumb_son.rb
100
+ - spec/examples/smart/lib/smart_base.rb
101
+ - spec/examples/smart/lib/smart_sons.rb
96
102
  - spec/spec_helper.rb
97
103
  homepage: http://github.com/djlebersilvestre/descendants-loader
98
104
  licenses:
@@ -104,17 +110,17 @@ require_paths:
104
110
  - lib
105
111
  required_ruby_version: !ruby/object:Gem::Requirement
106
112
  requirements:
107
- - - ">="
113
+ - - ! '>='
108
114
  - !ruby/object:Gem::Version
109
- version: 2.0.0
115
+ version: 1.9.3
110
116
  required_rubygems_version: !ruby/object:Gem::Requirement
111
117
  requirements:
112
- - - ">="
118
+ - - ! '>='
113
119
  - !ruby/object:Gem::Version
114
120
  version: '0'
115
121
  requirements: []
116
122
  rubyforge_project:
117
- rubygems_version: 2.4.6
123
+ rubygems_version: 2.4.5
118
124
  signing_key:
119
125
  specification_version: 4
120
126
  summary: This gem is an Object.descendants and Object.subclasses loader. The desired
@@ -123,3 +129,9 @@ summary: This gem is an Object.descendants and Object.subclasses loader. The des
123
129
  check README.
124
130
  test_files:
125
131
  - spec/spec_helper.rb
132
+ - spec/examples/smart/lib/smart_sons.rb
133
+ - spec/examples/smart/lib/smart_base.rb
134
+ - spec/examples/dumb/lib/dumb_son.rb
135
+ - spec/examples/dumb/lib/dumb_base.rb
136
+ - spec/descendants_loader_spec.rb
137
+ - spec/descendants_loader/class_finder_spec.rb