clafamatt 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/#README.rdoc# +119 -0
- data/History.txt +4 -0
- data/Manifest.txt +24 -0
- data/README.rdoc +119 -0
- data/Rakefile +46 -0
- data/bin/clafamatt +8 -0
- data/examples/synopsys.rb +38 -0
- data/lib/clafamatt.rb +168 -0
- data/spec/clafamatt_spec.rb +269 -0
- data/spec/spec_helper.rb +16 -0
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/gem.rake +192 -0
- data/tasks/git.rake +40 -0
- data/tasks/manifest.rake +48 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +39 -0
- data/tasks/rdoc.rake +50 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +279 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- data/test/test_clafamatt.rb +0 -0
- metadata +88 -0
data/#README.rdoc#
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
clafamatt
|
2
|
+
by Avdi Grimm
|
3
|
+
http://clafamatt.rubyforge.org
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
ClaFamAtt (CLAss FAMily ATTributes) gives you class inheritable attributes
|
8
|
+
without all that tedious mucking about with +@inheritable_attributes+.
|
9
|
+
|
10
|
+
== FEATURES
|
11
|
+
|
12
|
+
* Fully Spec'd
|
13
|
+
* reader/writer methods are cleanly partitioned in dynamically created modules
|
14
|
+
* No extra class variables needed for bookkeeping
|
15
|
+
* Reader/writer methods are defined once and only once no matter how many classes
|
16
|
+
inherit them
|
17
|
+
* Family inheritable attributes can be defined in modules
|
18
|
+
* Will not pollute the global namespace.
|
19
|
+
|
20
|
+
== SYNOPSIS:
|
21
|
+
|
22
|
+
module Shared
|
23
|
+
include Clafamatt::Macros
|
24
|
+
|
25
|
+
class_family_accessor :foo
|
26
|
+
end
|
27
|
+
|
28
|
+
class Parent
|
29
|
+
include Shared
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
class Child < Parent
|
34
|
+
class_family_accessor :bar
|
35
|
+
end
|
36
|
+
|
37
|
+
Shared.foo # => nil
|
38
|
+
Parent.foo # => nil
|
39
|
+
Child.foo # => nil
|
40
|
+
|
41
|
+
Shared.foo = "klaatu"
|
42
|
+
Shared.foo # => "klaatu"
|
43
|
+
Parent.foo # => "klaatu"
|
44
|
+
Child.foo # => "klaatu"
|
45
|
+
|
46
|
+
Parent.foo = "nikto"
|
47
|
+
Shared.foo # => "klaatu"
|
48
|
+
Parent.foo # => "nikto"
|
49
|
+
Child.foo # => "nikto"
|
50
|
+
|
51
|
+
Child.foo = "barada"
|
52
|
+
Shared.foo # => "klaatu"
|
53
|
+
Parent.foo # => "nikto"
|
54
|
+
Child.foo # => "barada"
|
55
|
+
|
56
|
+
Child.bar = "klaatu"
|
57
|
+
Child.bar # => "klaatu"
|
58
|
+
Parent.bar # =>
|
59
|
+
# ~> -:38: undefined method `bar' for Parent:Class (NoMethodError)
|
60
|
+
|
61
|
+
== RATIONALE:
|
62
|
+
|
63
|
+
Clafamatt sprung from a desire to have ActiveSupport-style class inheritable
|
64
|
+
attributes without having all of ActiveSupport come with it. It is also an
|
65
|
+
attempt to implement class-inheritable attributes in the cleanest way possible.
|
66
|
+
|
67
|
+
In contrast to the ActiveSupport version, which writes reader/writer methods
|
68
|
+
directly into the class being extended, Clafamatt writes it's readers and
|
69
|
+
writers into a dynamically created module which is then inserted into the class'
|
70
|
+
(or module's) singleton class. Among other benefits, this enables Clafamatt to
|
71
|
+
transparently support defining inheritable attributes in either classes or
|
72
|
+
modules.
|
73
|
+
|
74
|
+
The ActiveSupport version keeps inheritable attribute values in a class-level
|
75
|
+
@inheritable_attributes variable, which it copies whenever a new class is
|
76
|
+
inherited. Clafamatt stays closer to Ruby conventions by storing each
|
77
|
+
attribute's value in a correspondingly-named class instance variable - so
|
78
|
+
e.g. <code>Foo.bar = 42</code> will set the <code>@bar</code> instance variable.
|
79
|
+
This is consistent with how Ruby's built-in attr_* macros behave. Beyond the
|
80
|
+
variables used to store values, Clafamatt needs *zero* class instance variables
|
81
|
+
for internal bookeeping. It also doesn't copy variables on inheritance;
|
82
|
+
instead, it simply re-uses values from farther up the inheritance chain until an
|
83
|
+
attribute is explicitly set.
|
84
|
+
|
85
|
+
Finally, Clafamatt is only there when you ask for it, by including
|
86
|
+
Clafamatt::Macros. It will not pollute the global namespace.
|
87
|
+
|
88
|
+
== REQUIREMENTS:
|
89
|
+
|
90
|
+
* Ruby!
|
91
|
+
|
92
|
+
== INSTALL:
|
93
|
+
|
94
|
+
sudo gem install clafamatt
|
95
|
+
|
96
|
+
== LICENSE:
|
97
|
+
|
98
|
+
(The MIT License)
|
99
|
+
|
100
|
+
Copyright (c) 2008 Avdi Grimm
|
101
|
+
|
102
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
103
|
+
a copy of this software and associated documentation files (the
|
104
|
+
'Software'), to deal in the Software without restriction, including
|
105
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
106
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
107
|
+
permit persons to whom the Software is furnished to do so, subject to
|
108
|
+
the following conditions:
|
109
|
+
|
110
|
+
The above copyright notice and this permission notice shall be
|
111
|
+
included in all copies or substantial portions of the Software.
|
112
|
+
|
113
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
114
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
115
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
116
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
117
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
118
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
119
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#README.rdoc#
|
2
|
+
History.txt
|
3
|
+
Manifest.txt
|
4
|
+
README.rdoc
|
5
|
+
Rakefile
|
6
|
+
bin/clafamatt
|
7
|
+
examples/synopsys.rb
|
8
|
+
lib/clafamatt.rb
|
9
|
+
spec/clafamatt_spec.rb
|
10
|
+
spec/spec_helper.rb
|
11
|
+
tasks/ann.rake
|
12
|
+
tasks/bones.rake
|
13
|
+
tasks/gem.rake
|
14
|
+
tasks/git.rake
|
15
|
+
tasks/manifest.rake
|
16
|
+
tasks/notes.rake
|
17
|
+
tasks/post_load.rake
|
18
|
+
tasks/rdoc.rake
|
19
|
+
tasks/rubyforge.rake
|
20
|
+
tasks/setup.rb
|
21
|
+
tasks/spec.rake
|
22
|
+
tasks/svn.rake
|
23
|
+
tasks/test.rake
|
24
|
+
test/test_clafamatt.rb
|
data/README.rdoc
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
clafamatt
|
2
|
+
by Avdi Grimm
|
3
|
+
http://clafamatt.rubyforge.org
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
ClaFamAtt (CLAss FAMily ATTributes) gives you class inheritable attributes
|
8
|
+
without all that tedious mucking about with +@inheritable_attributes+.
|
9
|
+
|
10
|
+
== FEATURES
|
11
|
+
|
12
|
+
* Fully Spec'd
|
13
|
+
* reader/writer methods are cleanly partitioned in dynamically created modules
|
14
|
+
* No extra class variables needed for bookkeeping
|
15
|
+
* Reader/writer methods are defined once and only once no matter how many classes
|
16
|
+
inherit them
|
17
|
+
* Family inheritable attributes can be defined in modules
|
18
|
+
* Will not pollute the global namespace.
|
19
|
+
|
20
|
+
== SYNOPSIS:
|
21
|
+
|
22
|
+
module Shared
|
23
|
+
include Clafamatt::Macros
|
24
|
+
|
25
|
+
class_family_accessor :foo
|
26
|
+
end
|
27
|
+
|
28
|
+
class Parent
|
29
|
+
include Shared
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
class Child < Parent
|
34
|
+
class_family_accessor :bar
|
35
|
+
end
|
36
|
+
|
37
|
+
Shared.foo # => nil
|
38
|
+
Parent.foo # => nil
|
39
|
+
Child.foo # => nil
|
40
|
+
|
41
|
+
Shared.foo = "klaatu"
|
42
|
+
Shared.foo # => "klaatu"
|
43
|
+
Parent.foo # => "klaatu"
|
44
|
+
Child.foo # => "klaatu"
|
45
|
+
|
46
|
+
Parent.foo = "nikto"
|
47
|
+
Shared.foo # => "klaatu"
|
48
|
+
Parent.foo # => "nikto"
|
49
|
+
Child.foo # => "nikto"
|
50
|
+
|
51
|
+
Child.foo = "barada"
|
52
|
+
Shared.foo # => "klaatu"
|
53
|
+
Parent.foo # => "nikto"
|
54
|
+
Child.foo # => "barada"
|
55
|
+
|
56
|
+
Child.bar = "klaatu"
|
57
|
+
Child.bar # => "klaatu"
|
58
|
+
Parent.bar # =>
|
59
|
+
# ~> -:38: undefined method `bar' for Parent:Class (NoMethodError)
|
60
|
+
|
61
|
+
== RATIONALE:
|
62
|
+
|
63
|
+
Clafamatt sprung from a desire to have ActiveSupport-style class inheritable
|
64
|
+
attributes without having all of ActiveSupport come with it. It is also an
|
65
|
+
attempt to implement class-inheritable attributes in the cleanest way possible.
|
66
|
+
|
67
|
+
In contrast to the ActiveSupport version, which writes reader/writer methods
|
68
|
+
directly into the class being extended, Clafamatt writes it's readers and
|
69
|
+
writers into a dynamically created module which is then inserted into the class'
|
70
|
+
(or module's) singleton class. Among other benefits, this enables Clafamatt to
|
71
|
+
transparently support defining inheritable attributes in either classes or
|
72
|
+
modules.
|
73
|
+
|
74
|
+
The ActiveSupport version keeps inheritable attribute values in a class-level
|
75
|
+
@inheritable_attributes variable, which it copies whenever a new class is
|
76
|
+
inherited. Clafamatt stays closer to Ruby conventions by storing each
|
77
|
+
attribute's value in a correspondingly-named class instance variable - so
|
78
|
+
e.g. <code>Foo.bar = 42</code> will set the <code>@bar</code> instance variable. This is
|
79
|
+
consistent with how Ruby's built-in attr_* macros behave. Beyond the variables
|
80
|
+
used to store values, Clafamatt needs *zero* class instance variables for
|
81
|
+
internal bookeeping. It also doesn't copy variables on inheritance; instead, it
|
82
|
+
simply re-uses values from farther up the inheritance chain until an attribute
|
83
|
+
is explicitly set.
|
84
|
+
|
85
|
+
Finally, Clafamatt is only there when you ask for it, by including
|
86
|
+
Clafamatt::Macros. It will not pollute the global namespace.
|
87
|
+
|
88
|
+
== REQUIREMENTS:
|
89
|
+
|
90
|
+
* Ruby!
|
91
|
+
|
92
|
+
== INSTALL:
|
93
|
+
|
94
|
+
sudo gem install clafamatt
|
95
|
+
|
96
|
+
== LICENSE:
|
97
|
+
|
98
|
+
(The MIT License)
|
99
|
+
|
100
|
+
Copyright (c) 2008 Avdi Grimm
|
101
|
+
|
102
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
103
|
+
a copy of this software and associated documentation files (the
|
104
|
+
'Software'), to deal in the Software without restriction, including
|
105
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
106
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
107
|
+
permit persons to whom the Software is furnished to do so, subject to
|
108
|
+
the following conditions:
|
109
|
+
|
110
|
+
The above copyright notice and this permission notice shall be
|
111
|
+
included in all copies or substantial portions of the Software.
|
112
|
+
|
113
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
114
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
115
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
116
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
117
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
118
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
119
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# Look in the tasks/setup.rb file for the various options that can be
|
2
|
+
# configured in this Rakefile. The .rake files in the tasks directory
|
3
|
+
# are where the options are used.
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bones'
|
7
|
+
Bones.setup
|
8
|
+
rescue LoadError
|
9
|
+
load 'tasks/setup.rb'
|
10
|
+
end
|
11
|
+
|
12
|
+
ensure_in_path 'lib'
|
13
|
+
require 'clafamatt'
|
14
|
+
|
15
|
+
task :default => 'spec:run'
|
16
|
+
|
17
|
+
PROJ.name = 'clafamatt'
|
18
|
+
PROJ.authors = 'Avdi Grimm'
|
19
|
+
PROJ.email = 'avdi@avdi.org'
|
20
|
+
PROJ.url = 'http://clafamatt.rubyforge.org'
|
21
|
+
PROJ.version = Clafamatt::VERSION
|
22
|
+
PROJ.rubyforge.name = 'clafamatt'
|
23
|
+
PROJ.readme_file = 'README.rdoc'
|
24
|
+
|
25
|
+
# Uncomment to disable warnings
|
26
|
+
# PROJ.ruby_opts = []
|
27
|
+
|
28
|
+
# RSpec
|
29
|
+
PROJ.spec.opts << '--color'
|
30
|
+
|
31
|
+
# RDoc
|
32
|
+
PROJ.rdoc.include << '\.rdoc$'
|
33
|
+
|
34
|
+
# Email Announcement
|
35
|
+
PROJ.ann.email[:from] = 'avdi@avdi.org'
|
36
|
+
PROJ.ann.email[:to] = 'ruby-talk@ruby-lang.org'
|
37
|
+
PROJ.ann.email[:server] = 'smtp.gmail.com'
|
38
|
+
PROJ.ann.email[:domain] = 'avdi.org'
|
39
|
+
PROJ.ann.email[:port] = 587
|
40
|
+
PROJ.ann.email[:acct] = 'avdi.grimm'
|
41
|
+
PROJ.ann.email[:authtype] = :plain
|
42
|
+
|
43
|
+
# Notes
|
44
|
+
PROJ.notes.extensions << '.rdoc'
|
45
|
+
|
46
|
+
# EOF
|
data/bin/clafamatt
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.expand_path('../lib/clafamatt', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
module Shared
|
4
|
+
include Clafamatt::Macros
|
5
|
+
|
6
|
+
class_family_accessor :foo
|
7
|
+
end
|
8
|
+
|
9
|
+
class Parent
|
10
|
+
include Shared
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
class Child < Parent
|
15
|
+
class_family_accessor :bar
|
16
|
+
end
|
17
|
+
|
18
|
+
Shared.foo # =>
|
19
|
+
Parent.foo # =>
|
20
|
+
Child.foo # =>
|
21
|
+
|
22
|
+
Shared.foo = "klaatu"
|
23
|
+
Shared.foo # =>
|
24
|
+
Parent.foo # =>
|
25
|
+
Child.foo # =>
|
26
|
+
|
27
|
+
Parent.foo = "nikto"
|
28
|
+
Shared.foo # =>
|
29
|
+
Parent.foo # =>
|
30
|
+
Child.foo # =>
|
31
|
+
|
32
|
+
Child.foo = "barada"
|
33
|
+
Parent.foo # =>
|
34
|
+
Child.foo # =>
|
35
|
+
|
36
|
+
Child.bar = "klaatu"
|
37
|
+
Child.bar # =>
|
38
|
+
Parent.bar # =>
|
data/lib/clafamatt.rb
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
module Clafamatt
|
2
|
+
|
3
|
+
# :stopdoc:
|
4
|
+
VERSION = '1.0.0'
|
5
|
+
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
6
|
+
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
7
|
+
|
8
|
+
# Returns the version string for the library.
|
9
|
+
#
|
10
|
+
def self.version
|
11
|
+
VERSION
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the library path for the module. If any arguments are given,
|
15
|
+
# they will be joined to the end of the libray path using
|
16
|
+
# <tt>File.join</tt>.
|
17
|
+
#
|
18
|
+
def self.libpath( *args )
|
19
|
+
args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the lpath for the module. If any arguments are given,
|
23
|
+
# they will be joined to the end of the path using
|
24
|
+
# <tt>File.join</tt>.
|
25
|
+
#
|
26
|
+
def self.path( *args )
|
27
|
+
args.empty? ? PATH : ::File.join(PATH, args.flatten)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Utility method used to rquire all files ending in .rb that lie in the
|
31
|
+
# directory below this file that has the same name as the filename passed
|
32
|
+
# in. Optionally, a specific _directory_ name can be passed in such that
|
33
|
+
# the _filename_ does not have to be equivalent to the directory.
|
34
|
+
#
|
35
|
+
def self.require_all_libs_relative_to( fname, dir = nil )
|
36
|
+
dir ||= ::File.basename(fname, '.*')
|
37
|
+
search_me = ::File.expand_path(
|
38
|
+
::File.join(::File.dirname(fname), dir, '*', '*.rb'))
|
39
|
+
|
40
|
+
Dir.glob(search_me).sort.each {|rb| require rb}
|
41
|
+
end
|
42
|
+
# :startdoc:
|
43
|
+
|
44
|
+
# This might be better named SingletonModule. A MacroModule acts as a
|
45
|
+
# container for singleton methods attached to a given class or module. This
|
46
|
+
# way we can share singleton methods across arbitrary classes and modules.
|
47
|
+
#
|
48
|
+
# MacroModule also ensures that the class being "decorated" with a MacroModule
|
49
|
+
# of its own will also inherit all of its ancestors' macros.
|
50
|
+
class MacroModule < Module
|
51
|
+
def self.find_or_create_for(klass)
|
52
|
+
mod = self.new(klass)
|
53
|
+
extend_klass = lambda do
|
54
|
+
mod.extend_class!
|
55
|
+
mod
|
56
|
+
end
|
57
|
+
klass_singleton = class << klass; self; end
|
58
|
+
klass_singleton.ancestors.find(extend_klass){|a|
|
59
|
+
a == mod
|
60
|
+
}
|
61
|
+
end
|
62
|
+
def self.find_all_for(klass)
|
63
|
+
klass_singleton = class << klass; self; end
|
64
|
+
klass_singleton.ancestors.grep(MacroModule)
|
65
|
+
end
|
66
|
+
def initialize(decorated_class)
|
67
|
+
@decorated_class = decorated_class
|
68
|
+
end
|
69
|
+
|
70
|
+
def ==(other)
|
71
|
+
self.class == other.class && self.decorated_class == other.decorated_class
|
72
|
+
end
|
73
|
+
|
74
|
+
def inspect
|
75
|
+
"#<Clafamatt::MacroModule:#{@decorated_class}:(#{self.instance_methods(false).join(", ")})>"
|
76
|
+
end
|
77
|
+
|
78
|
+
def copy_ancestor_macro_modules!
|
79
|
+
@decorated_class.ancestors.each do |ancestor|
|
80
|
+
macro_modules = self.class.find_all_for(ancestor)
|
81
|
+
macro_modules.each do |mm|
|
82
|
+
@decorated_class.extend(mm)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def extend_class!
|
88
|
+
copy_ancestor_macro_modules!
|
89
|
+
@decorated_class.extend(self)
|
90
|
+
end
|
91
|
+
attr_reader :decorated_class
|
92
|
+
end
|
93
|
+
|
94
|
+
module Macros
|
95
|
+
def self.append_features(other)
|
96
|
+
other.extend(ClassMethods)
|
97
|
+
super(other)
|
98
|
+
end
|
99
|
+
|
100
|
+
module ClassMethods
|
101
|
+
def class_family_reader(*symbols)
|
102
|
+
symbols.each do |name|
|
103
|
+
ivar = '@' + name.to_s
|
104
|
+
define_macro(name) do ||
|
105
|
+
# Explicitly checking for variable definition avoids warnings.
|
106
|
+
if instance_variable_defined?(ivar)
|
107
|
+
instance_variable_get(ivar)
|
108
|
+
# super() doesn't work the way we need in singleton class world
|
109
|
+
elsif can_pass?(name)
|
110
|
+
pass(name)
|
111
|
+
else
|
112
|
+
nil
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
def class_family_writer(*symbols)
|
118
|
+
symbols.each do |name|
|
119
|
+
setter = name.to_s + '='
|
120
|
+
ivar = '@' + name.to_s
|
121
|
+
define_macro(setter) do |new_value|
|
122
|
+
instance_variable_set(ivar, new_value)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
def class_family_accessor(*symbols)
|
127
|
+
class_family_reader(*symbols)
|
128
|
+
class_family_writer(*symbols)
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
def append_features(other)
|
134
|
+
other.extend(ClassMethods)
|
135
|
+
cmm = clafamatt_macro_module
|
136
|
+
other.extend(cmm)
|
137
|
+
super(other)
|
138
|
+
end
|
139
|
+
|
140
|
+
def define_macro(name, &block)
|
141
|
+
cmm = clafamatt_macro_module
|
142
|
+
cmm.module_eval do
|
143
|
+
define_method(name, &block)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def clafamatt_macro_module
|
148
|
+
MacroModule.find_or_create_for(self)
|
149
|
+
end
|
150
|
+
|
151
|
+
def next_ancestor_responding_to(method)
|
152
|
+
ancestors.slice(1..-1).detect{|a| a.respond_to?(method)}
|
153
|
+
end
|
154
|
+
|
155
|
+
def can_pass?(method)
|
156
|
+
next_ancestor_responding_to(method)
|
157
|
+
end
|
158
|
+
|
159
|
+
def pass(method, *args, &block)
|
160
|
+
next_ancestor_responding_to(method).send(method, *args, &block)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end # module Clafamatt
|
165
|
+
|
166
|
+
Clafamatt.require_all_libs_relative_to(__FILE__)
|
167
|
+
|
168
|
+
# EOF
|