dyoder-autocode 0.9.8 → 0.9.9

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
@@ -6,56 +6,55 @@ module AutoCode
6
6
  cname.gsub(/(_)(\w)/) { $2.upcase }.gsub(/^([a-z])/) { $1.upcase }.intern
7
7
  end
8
8
 
9
- class Loader
10
- def initialize(options={}); @directories = options[:directories] ; end
11
- def call(cname)
12
- filename = Loader.snake_case( cname ) << '.rb'
13
- if @directories.nil?
14
- Kernel.load( filename )
15
- else
16
- path = @directories.map { |dir| File.join( dir.to_s, filename ) }.find { |path| File.exist?( path ) }
17
- Kernel.load( path ) rescue nil unless path.nil?
18
- end
19
- end
20
- def Loader.snake_case(cname)
21
- cname.to_s.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').downcase
22
- end
9
+ def AutoCode.snake_case( cname )
10
+ cname.to_s.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').downcase
23
11
  end
24
-
25
- class Creator
26
- def initialize( options, &block )
27
- @exemplar = (options[:exemplar]||Module.new).clone; @block = block
28
- end
29
- def call ; @exemplar.module_eval( &@block ) if @block ; @exemplar ; end
30
- end
31
-
32
- class Initializer
33
- def initialize( &block ) ;@block = block ; end
34
- def call( mod ) ; mod.module_eval( &@block ) ; end
35
- end
36
-
37
- def self.extended( mod ) ; included(mod) ; end
12
+
13
+ def self.extended( mod ) ; included( mod ) ; end
38
14
 
39
15
  def self.included( mod )
40
16
 
41
17
  mod.instance_eval do
42
18
 
19
+ # First make sure we haven't already done this once
20
+ return unless @autocode.nil?
21
+
43
22
  # Initialize bookkeeping variables needed by AutoCode
44
- @initializers ||= Hash.new { |h,k| h[k] = [] }; @reloadable ||= []
23
+ @autocode = {
24
+ :constructors => Hash.new { |h,k| h[k] = [] },
25
+ :initializers => Hash.new { |h,k| h[k] = [] },
26
+ :loaded => []
27
+ }
45
28
 
46
29
  # Adds an auto_create block for the given key using the given exemplar if provided
47
30
  def auto_create( key = true, options = {}, &block )
48
- @initializers[ AutoCode.normalize( key ) ] << Creator.new( options, &block ); self
31
+ @autocode[:constructors][ AutoCode.normalize( key ) ] << lambda do | cname |
32
+ exemplar = ( options[:exemplar] || Module.new ).clone
33
+ exemplar.module_eval( &block ) if block
34
+ const_set( cname, exemplar )
35
+ end
49
36
  end
50
37
 
51
38
  # Adds an auto_load block for the given key and directories
52
39
  def auto_load( key = true, options = {} )
53
- @initializers[ AutoCode.normalize( key ) ].unshift( Loader.new( options ) ); self
40
+ @autocode[:constructors][ AutoCode.normalize( key ) ] << lambda do | cname |
41
+ filename = AutoCode.snake_case( cname ) << '.rb'
42
+ if options[:directories].nil?
43
+ Kernel.load( filename ) if File.exist?( filename )
44
+ else
45
+ path = options[:directories].
46
+ map { |dir| File.join( dir.to_s, filename ) }.
47
+ find { |path| File.exist?( path ) }
48
+ Kernel.load( path ) unless path.nil?
49
+ end
50
+ end
54
51
  end
55
52
 
56
53
  # Adds an arbitrary initializer block for the given key
57
54
  def auto_eval( key, &block )
58
- @initializers[ AutoCode.normalize( key ) ] << Initializer.new( &block ); self
55
+ @autocode[:initializers][ AutoCode.normalize( key ) ] << lambda do | mod |
56
+ mod.module_eval( &block )
57
+ end
59
58
  end
60
59
 
61
60
  # Convenience method for auto_create.
@@ -68,37 +67,26 @@ module AutoCode
68
67
  auto_create( key,{ :exemplar => Module.new }, &block )
69
68
  end
70
69
 
71
- # Reloading stuff ...
72
-
73
70
  # Returns the list of constants that would be reloaded upon a call to reload.
74
- def reloadable( *names ) ; @reloadable + names ; end
71
+ def reloadable ; @autocode[:loaded] ; end
75
72
 
76
- # Reloads all the constants that were loaded via auto_code. Technically, all reload
77
- # is doing is undefining them (by calling +remove_const+ on each in turn); they won't get
78
- # reloaded until they are referenced.
79
- def reload ; @reloadable.each { |name| remove_const( name ) } ; @reloadable = [] ; self; end
80
-
81
- # Unloads all the constants that were loaded and removes all auto* definitions.
82
- def unload ; reload ; @initializers = Hash.new { |h,k| h[k] = [] } ; self ; end
73
+ # Reloads (via #remove_const) all the constants that were loaded via auto_code.
74
+ def reload ; @autocode[:loaded].each { |name| remove_const( name ) } ; @autocode[:loaded] = [] ; end
83
75
 
84
76
  private
85
77
 
86
78
  old = method( :const_missing )
87
79
  (class << self ; self ; end ).instance_eval do
88
- define_method :const_missing do | cname |
89
- ( @initializers[cname] + @initializers[true] ).each do |initializer|
90
- case initializer
91
- when Loader then initializer.call( cname ) unless const_defined?(cname)
92
- when Creator then const_set( cname, initializer.call ) unless const_defined?(cname)
93
- else
94
- return old.call(cname) unless const_defined?( cname )
95
- initializer.call( const_get( cname ) ) if const_defined?( cname )
96
- end
97
- end
98
- return old.call(cname) unless const_defined?( cname )
99
- @reloadable << cname ; const_get( cname )
80
+ define_method( :const_missing ) do | cname |
81
+ constructors = @autocode[:constructors][true] + @autocode[:constructors][cname]
82
+ constructors.pop.call( cname ) until ( const_defined?( cname ) or constructors.empty? )
83
+ return old.call( cname ) unless const_defined?( cname )
84
+ initializers = @autocode[:initializers][true] + @autocode[:initializers][cname]
85
+ mod = const_get( cname ) ; initializers.pop.call( mod ) until initializers.empty?
86
+ @autocode[:loaded] << cname ; const_get( cname )
100
87
  end
101
88
  end
102
89
  end
103
90
  end
104
- end
91
+ end
92
+ Autocode = AutoCode
data/test/auto_create.rb CHANGED
@@ -3,7 +3,7 @@ require File.join(File.dirname(__FILE__), 'helpers.rb')
3
3
  describe "auto_create should" do
4
4
 
5
5
  before do
6
- A.unload if defined? A and A.respond_to? :unload
6
+ Object.instance_eval { remove_const(:A) if const_defined?(:A) }
7
7
  module A
8
8
  include AutoCode
9
9
  auto_create_module :B do
data/test/auto_eval.rb CHANGED
@@ -3,7 +3,7 @@ require File.join(File.dirname(__FILE__), 'helpers.rb')
3
3
  describe "auto_eval should" do
4
4
 
5
5
  before do
6
- A.unload if defined? A and A.respond_to? :unload
6
+ Object.instance_eval { remove_const(:A) if const_defined?(:A) }
7
7
  module A
8
8
  include AutoCode
9
9
  auto_create_module :B
@@ -14,8 +14,8 @@ describe "auto_eval should" do
14
14
  end
15
15
  A.auto_eval :B do
16
16
  include AutoCode
17
- auto_eval :R do
18
- def self.foo; end
17
+ auto_eval :C do
18
+ self::D = true
19
19
  end
20
20
  end
21
21
  end
@@ -24,8 +24,8 @@ describe "auto_eval should" do
24
24
  A::B::C.class.should == Class
25
25
  end
26
26
 
27
- specify "work inside an auto_* block" do
28
- A::B::R.class.should == Class
27
+ specify "allow you to define nested auto_eval declarations" do
28
+ A::B::C::D.should == true
29
29
  end
30
30
 
31
31
  end
data/test/auto_load.rb CHANGED
@@ -5,8 +5,8 @@ require 'extensions/io'
5
5
  describe "auto_load should" do
6
6
 
7
7
  before do
8
- A.unload if defined? A and A.respond_to? :unload
9
- FileUtils.mkdir('tmp')
8
+ Object.instance_eval { remove_const(:A) if const_defined?(:A) }
9
+ FileUtils.mkdir('tmp') rescue nil
10
10
  @path = File.join( 'tmp', 'b.rb' )
11
11
  content =<<-EOF
12
12
  module A
@@ -19,7 +19,6 @@ describe "auto_load should" do
19
19
  include AutoCode
20
20
  auto_create_class :B
21
21
  auto_load :B, :directories => ['tmp']
22
- auto_create_class :B
23
22
  end
24
23
 
25
24
  end
@@ -33,20 +32,20 @@ describe "auto_load should" do
33
32
  A::B.class.should == Module
34
33
  end
35
34
 
35
+ specify "should implement LIFO semantics" do
36
+ A::B.class.should == Module
37
+ end
38
+
36
39
  specify "should raise a NameError if a const doesn't match" do
37
40
  lambda{ A::C }.should.raise NameError
38
41
  end
39
-
40
- specify "always take precedence over auto_create" do
41
- A::B.class.should == Module
42
- end
43
-
42
+
44
43
  specify "snake case the constant name which is used to map a constant to a filename" do
45
- AutoCode::Loader.snake_case(:Post).should == "post"
46
- AutoCode::Loader.snake_case(:GitHub).should == "git_hub"
47
- AutoCode::Loader.snake_case(:GITRepository).should == "git_repository"
48
- AutoCode::Loader.snake_case(:Git42Repository).should == "git42_repository"
49
- AutoCode::Loader.snake_case(:GIT42Repository).should == "git42_repository"
44
+ AutoCode.snake_case(:Post).should == "post"
45
+ AutoCode.snake_case(:GitHub).should == "git_hub"
46
+ AutoCode.snake_case(:GITRepository).should == "git_repository"
47
+ AutoCode.snake_case(:Git42Repository).should == "git42_repository"
48
+ AutoCode.snake_case(:GIT42Repository).should == "git42_repository"
50
49
  end
51
50
 
52
51
  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.8
4
+ version: 0.9.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Yoder
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-05-14 00:00:00 -07:00
12
+ date: 2008-05-15 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency