dyoder-autocode 0.9.5 → 0.9.6

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 CHANGED
@@ -1,134 +1,135 @@
1
1
  module Autocode
2
-
2
+
3
3
  def self.extended( mod )
4
4
  included(mod)
5
5
  end
6
-
7
- def self.included( mod )
8
-
9
- old = mod.method( :const_missing )
10
- mod.metaclass.class_eval do
11
-
12
- def autocreate( key, exemplar, &block )
13
- keys = case key
14
- when true, Symbol then [key]
15
- when Array then key
16
- end
17
-
18
- @exemplars ||= Hash.new
19
- @init_blocks ||= Hash.new { |h,k| h[k] = [] }
20
- keys.each do |k|
21
- @exemplars[k] = exemplar
6
+
7
+ def self.included( mod )
8
+
9
+ old = mod.method( :const_missing )
10
+ mod.metaclass.class_eval do
11
+
12
+ def autocreate( key, exemplar, &block )
13
+ keys = case key
14
+ when true, Symbol then [key]
15
+ when Array then key
16
+ end
17
+
18
+ @exemplars ||= Hash.new
19
+ @init_blocks ||= Hash.new { |h,k| h[k] = [] }
20
+ keys.each do |k|
21
+ @exemplars[k] = exemplar
22
22
  @init_blocks[k] << block
23
- end
24
-
25
- return self
26
- end
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
-
36
- def autoinit( key, &block )
37
- # See whether we're dealing with a namespaced constant,
38
- # The match groupings for, e.g. "X::Y::Z", would be
39
- # ["X::Y", "Z"]
40
- match = key.to_s.match(/^(.*)::([\w\d_]+)$/)
41
- if match
42
- namespace, cname = match[1,2]
43
- const = module_eval(namespace)
44
- const.module_eval do
45
- @init_blocks ||= Hash.new { |h,k| h[k] = [] }
46
- @init_blocks[cname.to_sym] << block
47
- end
48
- else
49
- @init_blocks[key] << block
50
- end
51
- return self
52
- end
53
-
54
- def autoload(key = true, options = {})
55
- snake_case = lambda {|name| name.gsub(/([a-z\d])([A-Z])/){"#{$1}_#{$2}"}.tr("-", "_").downcase }
56
- # look for load_files in either a specified directory, or in the directory
57
- # with the snakecase name of the enclosing module
58
- directories = [options[:directories] || snake_case.call(self.name.match( /^.*::([\w\d_]+)$/)[1])].flatten
23
+ end
24
+
25
+ return self
26
+ end
27
+
28
+ def autocreate_class( key = true, superclass = Class )
29
+ autocreate key, Class.new( superclass )
30
+ end
31
+
32
+ def autocreate_module( key = true )
33
+ autocreate key, Module.new
34
+ end
35
+
36
+ def autoinit( key, &block )
37
+ # See whether we're dealing with a namespaced constant,
38
+ # The match groupings for, e.g. "X::Y::Z", would be
39
+ # ["X::Y", "Z"]
40
+ match = key.to_s.match(/^(.*)::([\w\d_]+)$/)
41
+ if match
42
+ namespace, cname = match[1,2]
43
+ const = module_eval(namespace)
44
+ const.module_eval do
45
+ @init_blocks ||= Hash.new { |h,k| h[k] = [] }
46
+ @init_blocks[cname.to_sym] << block
47
+ end
48
+ else
49
+ @init_blocks[key] << block
50
+ end
51
+ return self
52
+ end
53
+
54
+ def autoload(key = true, options = {})
55
+ snake_case = lambda {|name| name.gsub(/([a-z\d])([A-Z])/){"#{$1}_#{$2}"}.tr("-", "_").downcase }
56
+ # look for load_files in either a specified directory, or in the directory
57
+ # with the snakecase name of the enclosing module
58
+ directories = [options[:directories] || snake_case.call(self.name.match( /^.*::([\w\d_]+)$/)[1])].flatten
59
59
  # create a lambda that looks for a file to load
60
60
  file_finder = lambda do |cname|
61
61
  filename = snake_case.call(cname.to_s << ".rb")
62
62
  path = directories.map { |dir| File.join(dir.to_s, filename) }.find { |path| File.exist?( path ) }
63
63
  end
64
64
  # if no exemplar is given, assume Module.new
65
- @load_files ||= Hash.new
65
+ @load_files ||= Hash.new
66
66
  @load_files[key] = [file_finder, options[:exemplar] || Module.new]
67
- return self
68
- end
69
-
70
- def autoload_class(key = true, superclass = nil, options = {})
71
- options[:exemplar] = Class.new(superclass)
72
- autoload key, options
73
- end
74
-
75
- def autoload_module(key = true, options = {})
76
- options[:exemplar] = Module.new
77
- autoload key, options
78
- end
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
-
67
+ return self
68
+ end
69
+
70
+ def autoload_class(key = true, superclass = Class, options = {})
71
+ options[:exemplar] = Class.new(superclass)
72
+ autoload key, options
73
+ end
74
+
75
+ def autoload_module(key = true, options = {})
76
+ options[:exemplar] = Module.new
77
+ autoload key, options
78
+ end
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
95
  # Unloads all the constants that were loaded and removes all auto* definitions.
96
- def unload
97
- reload
96
+ def unload
97
+ reload
98
98
  @exemplars = @init_blocks = @load_files = nil
99
- return self
100
- end
101
-
102
- private
103
-
104
- define_method :const_missing do | cname | #:nodoc:
99
+ return self
100
+ end
101
+
102
+ private
103
+
104
+ define_method :const_missing do | cname | #:nodoc:
105
105
  cname = cname.to_sym
106
106
  @exemplars ||= Hash.new
107
107
  @init_blocks ||= Hash.new { |h,k| h[k] = [] }
108
- @load_files ||= Hash.new
108
+ @load_files ||= Hash.new
109
109
  exemplar = @exemplars[cname] || @exemplars[true]
110
110
  blocks = @init_blocks[cname]
111
111
  blocks = @init_blocks[true] + blocks if @exemplars[cname].nil? && @init_blocks[true]
112
112
  load_file_finder, load_class = @load_files[cname] || @load_files[true]
113
-
114
- if load_file_finder && filename = load_file_finder.call(cname)
115
- object = load_class.clone
116
- elsif exemplar
117
- object = exemplar.clone
118
- else
119
- return old.call(cname)
120
- end
121
-
122
- (@reloadable ||= []) << cname;
123
- const_set( cname, object )
124
-
113
+
114
+ if load_file_finder && filename = load_file_finder.call(cname)
115
+ object = load_class.clone
116
+ elsif exemplar
117
+ object = exemplar.clone
118
+ else
119
+ return old.call(cname)
120
+ end
121
+
122
+ (@reloadable ||= []) << cname;
123
+ const_set( cname, object )
124
+
125
125
  blocks.each do |block|
126
126
  object.module_eval( &block) if block
127
127
  end
128
+
128
129
  load(filename) if filename
129
- return object
130
- end
131
-
132
- end
130
+
131
+ return object
132
+ end
133
+ end
133
134
  end
134
135
  end
data/test/autocreate.rb CHANGED
@@ -40,4 +40,21 @@ describe "A module where autocreate has been called" do
40
40
  Duffel.unload
41
41
  end
42
42
 
43
+ it "should be possible to include autocode" do
44
+ module Waves
45
+ include Autocode
46
+ autocreate(:TestLib, Module.new) do
47
+ include Autocode
48
+ autocreate_class
49
+ autoload_class
50
+ end
51
+ end
52
+ Waves::TestLib::TheOneAndOnlyClass.help().should == "class help"
53
+ Waves::TestLib::AnyThing.name.should == "Waves::TestLib::AnyThing"
54
+ lambda { Waves::TestLib::TheOneAndOnlyModule }.should.raise TypeError
55
+ Waves::TestLib::ThePretender.name.should == "Waves::TestLib::ThePretender"
56
+ lambda { Waves::TestLib::ThePretender.help() }.should.raise NoMethodError
57
+ Waves.unload
58
+ end
59
+
43
60
  end
data/test/autoinit.rb CHANGED
@@ -12,11 +12,11 @@ describe "thingy" do
12
12
  autoinit(:Whatsit) do
13
13
  def self.in_scope; true; end
14
14
  end
15
-
15
+
16
16
  autoinit('Whatsit::Critter') do
17
17
  def self.outside_scope; true; end
18
18
  def instance; true; end
19
- # this definition overrides the one in the file
19
+ # this definition is overridden by the one in the file
20
20
  def self.gizmo; 2; end
21
21
  end
22
22
 
@@ -54,6 +54,5 @@ describe "thingy" do
54
54
  it "should run autoinit blocks before the file loading" do
55
55
  Thingy::Whatsit::Critter.gizmo.should == 1
56
56
  end
57
-
58
-
57
+
59
58
  end
data/test/autoload.rb CHANGED
@@ -6,28 +6,14 @@ describe "A module where autoload has been called" do
6
6
  module Thingy
7
7
  module Mabob
8
8
  extend Autocode
9
- autoload_class true, Class, :directories => [File.join(File.dirname(__FILE__), "test_lib")]
9
+ autoload_class :DooDad, Class, :directories => [File.join(File.dirname(__FILE__), "test_lib")]
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
25
13
  end
26
14
 
27
15
  after do
28
16
  Thingy::Mabob.unload
29
- Waves::TestLib.unload
30
- Whatever::TestLib.unload
31
17
  end
32
18
 
33
19
  it "should autoload where files match" do
@@ -36,6 +22,7 @@ describe "A module where autoload has been called" do
36
22
  end
37
23
 
38
24
  it "should not autoload where it matches a file but is out of scope" do
25
+ lambda { Thingy::Mabob::Answer42ItIs }.should.raise NameError
39
26
  lambda { Thingy::Whatsit::Critter }.should.raise NameError
40
27
  end
41
28
 
@@ -43,12 +30,57 @@ describe "A module where autoload has been called" do
43
30
  lambda { Thingy::Mabob::MooCow }.should.raise NameError
44
31
  end
45
32
 
46
- it "should autoload using default directories" do
47
- Waves::TestLib::TheHelperModule.should.respond_to :help
33
+ it "should autoload using super class" do
34
+ module Waves
35
+ module TestLib
36
+ extend Autocode
37
+ autoload_class true, Thingy::Mabob::DooDad
38
+ end
39
+ end
40
+ Waves::TestLib::TheClass42Gang.party?.should == true
41
+ Waves::TestLib::TheClass42Gang.gizmo.should == 1
42
+ Waves::TestLib.unload
48
43
  end
49
44
 
50
- it "should allow default options" do
51
- Whatever::TestLib::TheOneAndOnly.should.respond_to :help
45
+ it "should autoload using defaults" do
46
+ module Waves
47
+ module TestLib
48
+ extend Autocode
49
+ autoload
50
+ end
51
+ end
52
+ Waves::TestLib::TheOneAndOnlyModule.help().should == "module help"
53
+ lambda { Waves::TestLib::TheOneAndOnlyClass }.should.raise TypeError
54
+ Waves::TestLib::ThePretender.name.should == "Waves::TestLib::ThePretender"
55
+ lambda { Waves::TestLib::ThePretender.help() }.should.raise NoMethodError
56
+ Waves::TestLib.unload
52
57
  end
53
58
 
59
+ it "should autoload class using defaults" do
60
+ module Waves
61
+ module TestLib
62
+ extend Autocode
63
+ autoload_class
64
+ end
65
+ end
66
+ Waves::TestLib::TheOneAndOnlyClass.help().should == "class help"
67
+ lambda { Waves::TestLib::TheOneAndOnlyModule }.should.raise TypeError
68
+ Waves::TestLib::ThePretender.name.should == "Waves::TestLib::ThePretender"
69
+ lambda { Waves::TestLib::ThePretender.help() }.should.raise NoMethodError
70
+ Waves::TestLib.unload
71
+ end
72
+
73
+ it "should autoload module using defaults" do
74
+ module Waves
75
+ module TestLib
76
+ extend Autocode
77
+ autoload_module
78
+ end
79
+ end
80
+ Waves::TestLib::TheOneAndOnlyModule.help().should == "module help"
81
+ lambda { Waves::TestLib::TheOneAndOnlyClass }.should.raise TypeError
82
+ Waves::TestLib::ThePretender.name.should == "Waves::TestLib::ThePretender"
83
+ lambda { Waves::TestLib::ThePretender.help() }.should.raise NoMethodError
84
+ Waves::TestLib.unload
85
+ end
54
86
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dyoder-autocode
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.5
4
+ version: 0.9.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Yoder