automatthew-auto_code 0.9.8

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.
@@ -0,0 +1,104 @@
1
+ module AutoCode
2
+
3
+ # always make sure we have a camel-cased symbol
4
+ def AutoCode.normalize( cname )
5
+ return cname unless cname.is_a? String
6
+ cname.gsub(/(_)(\w)/) { $2.upcase }.gsub(/^([a-z])/) { $1.upcase }.intern
7
+ end
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
23
+ 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
38
+
39
+ def self.included( mod )
40
+
41
+ mod.instance_eval do
42
+
43
+ # Initialize bookkeeping variables needed by AutoCode
44
+ @initializers = Hash.new { |h,k| h[k] = [] }; @reloadable = []
45
+
46
+ # Adds an auto_create block for the given key using the given exemplar if provided
47
+ def auto_create( key = true, options = {}, &block )
48
+ @initializers[ AutoCode.normalize( key ) ] << Creator.new( options, &block ); self
49
+ end
50
+
51
+ # Adds an auto_load block for the given key and directories
52
+ def auto_load( key = true, options = {} )
53
+ @initializers[ AutoCode.normalize( key ) ].unshift( Loader.new( options ) ); self
54
+ end
55
+
56
+ # Adds an arbitrary initializer block for the given key
57
+ def auto_eval( key, &block )
58
+ @initializers[ AutoCode.normalize( key ) ] << Initializer.new( &block ); self
59
+ end
60
+
61
+ # Convenience method for auto_create.
62
+ def auto_create_class( key = true, superclass = Object, &block )
63
+ auto_create( key,{ :exemplar => Class.new( superclass ) }, &block )
64
+ end
65
+
66
+ # Convenience method for auto_create.
67
+ def auto_create_module( key = true, &block )
68
+ auto_create( key,{ :exemplar => Module.new }, &block )
69
+ end
70
+
71
+ # Reloading stuff ...
72
+
73
+ # Returns the list of constants that would be reloaded upon a call to reload.
74
+ def reloadable( *names ) ; @reloadable + names ; end
75
+
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
83
+
84
+ private
85
+
86
+ old = method( :const_missing )
87
+ (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 )
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,28 @@
1
+ require File.join(File.dirname(__FILE__), 'helpers.rb')
2
+
3
+ describe "auto_create should" do
4
+
5
+ before do
6
+ A.unload if defined? A and A.respond_to? :unload
7
+ module A
8
+ include AutoCode
9
+ auto_create_module :B do
10
+ include AutoCode
11
+ auto_create_class
12
+ end
13
+ end
14
+ end
15
+
16
+ specify "allow you create and initialize a given const name" do
17
+ A::B.class.should == Module
18
+ end
19
+
20
+ specify "allow you create and initialize const using a wildcard" do
21
+ A::B::C.class.should === Class
22
+ end
23
+
24
+ specify "should raise a NameError if a const doesn't match" do
25
+ lambda{ A::C }.should.raise NameError
26
+ end
27
+
28
+ end
@@ -0,0 +1,21 @@
1
+ require File.join(File.dirname(__FILE__), 'helpers.rb')
2
+
3
+ describe "auto_eval should" do
4
+
5
+ before do
6
+ A.unload if defined? A and A.respond_to? :unload
7
+ module A
8
+ include AutoCode
9
+ auto_create_module :B
10
+ end
11
+ A.auto_eval :B do
12
+ include AutoCode
13
+ auto_create_class
14
+ end
15
+ end
16
+
17
+ specify "allow you to run blocks after an object is first created" do
18
+ A::B::C.class.should == Class
19
+ end
20
+
21
+ end
@@ -0,0 +1,52 @@
1
+ require File.join(File.dirname(__FILE__), 'helpers.rb')
2
+ require 'extensions/io'
3
+
4
+
5
+ describe "auto_load should" do
6
+
7
+ before do
8
+ A.unload if defined? A and A.respond_to? :unload
9
+ FileUtils.mkdir('tmp')
10
+ @path = File.join( 'tmp', 'b.rb' )
11
+ content =<<-EOF
12
+ module A
13
+ module B
14
+ end
15
+ end
16
+ EOF
17
+ File.write( @path, content )
18
+ module A
19
+ include AutoCode
20
+ auto_create_class :B
21
+ auto_load :B, :directories => ['tmp']
22
+ auto_create_class :B
23
+ end
24
+
25
+ end
26
+
27
+ after do
28
+ FileUtils.rm( File.join( @path ) )
29
+ FileUtils.rmdir( 'tmp' )
30
+ end
31
+
32
+ specify "allow you to load a file to define a const" do
33
+ A::B.class.should == Module
34
+ end
35
+
36
+ specify "should raise a NameError if a const doesn't match" do
37
+ lambda{ A::C }.should.raise NameError
38
+ end
39
+
40
+ specify "always take precedence over auto_create" do
41
+ A::B.class.should == Module
42
+ end
43
+
44
+ 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"
50
+ end
51
+
52
+ end
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ %w{ bacon metaid }.each { |dep| require dep }
3
+ # Bacon.extend Bacon::TestUnitOutput
4
+ Bacon.summary_on_exit
5
+
6
+ module Kernel
7
+ private
8
+ def specification(name, &block) Bacon::Context.new(name, &block) end
9
+ end
10
+
11
+ Bacon::Context.instance_eval do
12
+ alias_method :specify, :it
13
+ end
14
+
15
+ require '../lib/auto_code'
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: automatthew-auto_code
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.8
5
+ platform: ruby
6
+ authors:
7
+ - Dan Yoder
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-05-13 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: metaid
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ description:
25
+ email:
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files: []
31
+
32
+ files:
33
+ - lib/auto_code.rb
34
+ - test/auto_code.gemspec
35
+ - test/auto_create.rb
36
+ - test/auto_eval.rb
37
+ - test/auto_load.rb
38
+ - test/helpers.rb
39
+ has_rdoc: true
40
+ homepage: http://dev.zeraweb.com/
41
+ post_install_message:
42
+ rdoc_options: []
43
+
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 1.8.6
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.0.1
62
+ signing_key:
63
+ specification_version: 2
64
+ summary: Utility for auto-including, reloading, and generating classes and modules.
65
+ test_files: []
66
+