dyoder-autocode 0.9.3 → 0.9.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.
- data/lib/autocode.rb +46 -24
- data/test/autocreate.rb +5 -0
- data/test/autoinit.rb +7 -0
- data/test/autoload.rb +30 -0
- data/test/helpers.rb +2 -3
- metadata +1 -1
- data/lib/reloadable.rb +0 -30
data/lib/autocode.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
require 'reloadable'
|
2
|
-
|
3
1
|
module Autocode
|
2
|
+
|
3
|
+
def self.extended( mod )
|
4
|
+
included(mod)
|
5
|
+
end
|
4
6
|
|
5
|
-
def self.
|
7
|
+
def self.included( mod )
|
6
8
|
|
7
9
|
old = mod.method( :const_missing )
|
8
10
|
mod.metaclass.class_eval do
|
@@ -23,6 +25,14 @@ module Autocode
|
|
23
25
|
return self
|
24
26
|
end
|
25
27
|
|
28
|
+
def autocreate_class( key = true, superclass = nil )
|
29
|
+
autocreate key, Class.new( superclass )
|
30
|
+
end
|
31
|
+
|
32
|
+
def autocreate_module( key = true )
|
33
|
+
autocreate key, Module.new
|
34
|
+
end
|
35
|
+
|
26
36
|
def autoinit( key, &block )
|
27
37
|
# See whether we're dealing with a namespaced constant,
|
28
38
|
# The match groupings for, e.g. "X::Y::Z", would be
|
@@ -41,34 +51,55 @@ module Autocode
|
|
41
51
|
return self
|
42
52
|
end
|
43
53
|
|
44
|
-
def autoload(
|
54
|
+
def autoload(key = true, options = {})
|
55
|
+
snake_case = lambda {|name| name.gsub(/([a-z\d])([A-Z])/){"#{$1}_#{$2}"}.tr("-", "_").downcase }
|
45
56
|
# look for load_files in either a specified directory, or in the directory
|
46
57
|
# with the snakecase name of the enclosing module
|
47
|
-
directories = [options[:directories] ||
|
58
|
+
directories = [options[:directories] || snake_case.call(self.name.match( /^.*::([\w\d_]+)$/)[1])].flatten
|
48
59
|
# create a lambda that looks for a file to load
|
49
60
|
file_finder = lambda do |cname|
|
50
|
-
filename =
|
51
|
-
|
52
|
-
File.exist?(File.join(dir.to_s, filename))
|
53
|
-
end
|
54
|
-
dirname ? File.join(dirname.to_s, filename) : nil
|
61
|
+
filename = snake_case.call(cname.to_s << ".rb")
|
62
|
+
path = directories.map { |dir| File.join(dir.to_s, filename) }.find { |path| File.exist?( path ) }
|
55
63
|
end
|
56
64
|
# if no exemplar is given, assume Module.new
|
57
65
|
@load_files ||= Hash.new
|
58
|
-
@load_files[key] = [file_finder, options[:exemplar]]
|
66
|
+
@load_files[key] = [file_finder, options[:exemplar] || Module.new]
|
59
67
|
return self
|
60
68
|
end
|
61
69
|
|
62
|
-
def autoload_class(key, superclass=nil, options={})
|
70
|
+
def autoload_class(key = true, superclass = nil, options = {})
|
63
71
|
options[:exemplar] = Class.new(superclass)
|
64
72
|
autoload key, options
|
65
73
|
end
|
66
74
|
|
67
|
-
def autoload_module(key, options={})
|
75
|
+
def autoload_module(key = true, options = {})
|
68
76
|
options[:exemplar] = Module.new
|
69
77
|
autoload key, options
|
70
78
|
end
|
71
|
-
|
79
|
+
|
80
|
+
# Returns the list of constants that would be reloaded upon a call to reload.
|
81
|
+
def reloadable( *names )
|
82
|
+
( @reloadable ||= [] ).concat(names)
|
83
|
+
return self
|
84
|
+
end
|
85
|
+
|
86
|
+
# Reloads all the constants that were loaded via autocode. Technically, all reload
|
87
|
+
# is doing is undefining them (by calling +remove_const+ on each in turn); they won't get
|
88
|
+
# reloaded until they are referenced.
|
89
|
+
def reload
|
90
|
+
@reloadable.each { |name| remove_const( name ) } if @reloadable
|
91
|
+
@reloadable = nil
|
92
|
+
return self
|
93
|
+
end
|
94
|
+
|
95
|
+
# Unloads all the constants that were loaded and removes all auto* definitions.
|
96
|
+
def unload
|
97
|
+
reload
|
98
|
+
@exemplars = @init_blocks = @load_files = nil
|
99
|
+
return self
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
72
103
|
|
73
104
|
define_method :const_missing do | cname | #:nodoc:
|
74
105
|
cname = cname.to_sym
|
@@ -97,16 +128,7 @@ module Autocode
|
|
97
128
|
load(filename) if filename
|
98
129
|
return object
|
99
130
|
end
|
100
|
-
|
101
|
-
def default_file_name(cname)
|
102
|
-
( cname.to_s.gsub(/([a-z\d])([A-Z\d])/){ "#{$1}_#{$2}"} << ".rb" ).downcase
|
103
|
-
end
|
104
|
-
|
105
|
-
def default_directory(module_name)
|
106
|
-
m = self.name.match( /^.*::([\w\d_]+)$/)
|
107
|
-
m[1].snake_case
|
108
|
-
end
|
109
|
-
|
131
|
+
|
110
132
|
end
|
111
133
|
end
|
112
134
|
end
|
data/test/autocreate.rb
CHANGED
@@ -14,6 +14,10 @@ describe "A module where autocreate has been called" do
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
after do
|
18
|
+
Thingy.unload
|
19
|
+
end
|
20
|
+
|
17
21
|
it "should autocreate some constants" do
|
18
22
|
Thingy::Tom.peeps.should == true
|
19
23
|
Thingy::Dick.peeps.should == false
|
@@ -33,6 +37,7 @@ describe "A module where autocreate has been called" do
|
|
33
37
|
end
|
34
38
|
|
35
39
|
Duffel::AnyThing.universal.should == true
|
40
|
+
Duffel.unload
|
36
41
|
end
|
37
42
|
|
38
43
|
end
|
data/test/autoinit.rb
CHANGED
@@ -37,6 +37,13 @@ describe "thingy" do
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
+
after do
|
41
|
+
Thingy::Whatsit.unload
|
42
|
+
Thingy::Big::Bad.unload
|
43
|
+
Thingy::Big.unload
|
44
|
+
Thingy.unload
|
45
|
+
end
|
46
|
+
|
40
47
|
it "fdfdsf" do
|
41
48
|
Thingy::Whatsit.in_scope.should.be.true
|
42
49
|
Thingy::Whatsit::Critter.outside_scope.should.be.true
|
data/test/autoload.rb
CHANGED
@@ -10,15 +10,45 @@ describe "A module where autoload has been called" do
|
|
10
10
|
autoload_module :Humbug, :directories => [File.join(File.dirname(__FILE__), "test_lib")]
|
11
11
|
end
|
12
12
|
end
|
13
|
+
module Waves
|
14
|
+
module TestLib
|
15
|
+
extend Autocode
|
16
|
+
autoload true, :exemplar => Module.new
|
17
|
+
end
|
18
|
+
end
|
19
|
+
module Whatever
|
20
|
+
module TestLib
|
21
|
+
extend Autocode
|
22
|
+
autoload
|
23
|
+
end
|
24
|
+
end
|
13
25
|
end
|
14
26
|
|
27
|
+
after do
|
28
|
+
Thingy::Mabob.unload
|
29
|
+
Waves::TestLib.unload
|
30
|
+
Whatever::TestLib.unload
|
31
|
+
end
|
32
|
+
|
15
33
|
it "should autoload where files match" do
|
16
34
|
Thingy::Mabob::DooDad.should.respond_to :gizmo
|
17
35
|
Thingy::Mabob::Humbug.should.respond_to :full_of_it?
|
18
36
|
end
|
19
37
|
|
38
|
+
it "should not autoload where it matches a file but is out of scope" do
|
39
|
+
lambda { Thingy::Whatsit::Critter }.should.raise NameError
|
40
|
+
end
|
41
|
+
|
20
42
|
it "should not autocreate those unmentioned and fileable" do
|
21
43
|
lambda { Thingy::Mabob::MooCow }.should.raise NameError
|
22
44
|
end
|
23
45
|
|
46
|
+
it "should autoload using default directories" do
|
47
|
+
Waves::TestLib::TheHelperModule.should.respond_to :help
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should allow default options" do
|
51
|
+
Whatever::TestLib::TheOneAndOnly.should.respond_to :help
|
52
|
+
end
|
53
|
+
|
24
54
|
end
|
data/test/helpers.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
|
-
%w{ rubygems bacon}.each { |dep| require dep }
|
1
|
+
%w{ rubygems bacon metaid }.each { |dep| require dep }
|
2
2
|
Bacon.extend Bacon::TestUnitOutput
|
3
3
|
Bacon.summary_on_exit
|
4
4
|
|
5
|
-
$:.unshift File.join(File.dirname(__FILE__) , "lib")
|
5
|
+
$:.unshift File.join(File.dirname(__FILE__) , "../lib")
|
6
6
|
require 'autocode'
|
7
7
|
|
8
|
-
# Dir.chdir(File.dirname(__FILE__))
|
metadata
CHANGED
data/lib/reloadable.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'metaid'
|
3
|
-
|
4
|
-
# Reloadable simply makes it possible for a module's code to be reloaded. *Important*: Only code loaded via Autoload or Autocreate will be reloaded. Also, the module itself is not reloaded, only the modules and classes within it that were loaded via *Autocode*.
|
5
|
-
#
|
6
|
-
# To use Reloadable, simply extend a given module with Reloadable. This will add two methods to the module: reloadable and reload. These are described below.
|
7
|
-
|
8
|
-
module Reloadable
|
9
|
-
|
10
|
-
def self.extended( mod ) #:nodoc:
|
11
|
-
|
12
|
-
mod.metaclass.class_eval do
|
13
|
-
|
14
|
-
# Returns the list of constants that would be reloaded upon a call to reload.
|
15
|
-
def reloadable( *names )
|
16
|
-
( @reloadable ||= [] ).concat(names)
|
17
|
-
return self
|
18
|
-
end
|
19
|
-
|
20
|
-
# Reloads all the constants that were loaded via *Autocode*. Technically, all reload is doing is undefining them (by calling +remove_const+ on each in turn); they won't get reloaded until they are referenced.
|
21
|
-
def reload
|
22
|
-
( @reloadable ||=[] ).each { |name| remove_const( name ) }
|
23
|
-
@reloadable = []; return self
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|