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 +13 -5
- data/lib/descendants_loader.rb +32 -0
- data/lib/descendants_loader/class_finder.rb +11 -8
- data/lib/descendants_loader/version.rb +1 -1
- data/spec/descendants_loader/class_finder_spec.rb +56 -0
- data/spec/descendants_loader_spec.rb +36 -0
- data/spec/examples/dumb/lib/dumb_base.rb +5 -0
- data/spec/examples/dumb/lib/dumb_son.rb +5 -0
- data/spec/examples/smart/lib/smart_base.rb +7 -0
- data/spec/examples/smart/lib/smart_sons.rb +17 -0
- data/spec/spec_helper.rb +1 -1
- metadata +38 -26
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
N2Y2Y2QyYTAxODA0YzZkMjc4NjI1NzliOTdjZjc4ZDg3MDZhMTA1NA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZmQ3NjM4MDZiMzkxM2FkMTA3MmRjZGQ3OGIxMjIyM2VmYmI5ZWZiMQ==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MjE4Yjc4MzgwMjhiZTgyYmQ4MDk0ZWFiNjQyOGExY2EyNGUzZDU5YmE2ODhj
|
10
|
+
MjkyNGM3Y2M2MGY1YjhhYjU3OTVkYTlkYTI5YjRkODljNjVmNjY4NDU1ZmJj
|
11
|
+
NzgxMTEwZjQ2MTAxODgzNWMzZjFhNTdlMWE3OTlhYjY5YzFhYjY=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZWM3ZTM0M2QyMDIyZWMyNTAyZGQyNGQ5NDQ5NjBjNTc0YmQ4YTc5NzU0NmY0
|
14
|
+
OWY2Zjc5ZWYzY2Q0MTYwMmMwOTI3MGJiNzk2OTMyYTc5YmRjMjNjZWE2ODM4
|
15
|
+
Y2JjM2M1MDgyYjgwNWQ0YzNiMGRlYjYxNGFkMjRjNjBlN2ZmODI=
|
data/lib/descendants_loader.rb
CHANGED
@@ -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
|
@@ -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
|
data/spec/spec_helper.rb
CHANGED
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.
|
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: '
|
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: '
|
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:
|
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.
|
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
|