descendants-loader 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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