mixin 0.7.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +34 -12
- data/lib/mixin.rb +33 -73
- data/test/mixin_case.rb +56 -98
- data/test/test_subjects/clevers.rb +8 -9
- data/test/test_subjects/extenders.rb +2 -9
- data/test/test_subjects/hopons.rb +1 -7
- data/test/test_subjects/includers.rb +2 -10
- data/test/test_subjects/meepers.rb +5 -25
- data/test/test_subjects/nudgers.rb +5 -9
- data/test/test_subjects/scopers.rb +0 -14
- data/test/test_subjects/sleepers.rb +2 -10
- data/test/test_subjects/soopers.rb +9 -48
- data/test/test_subjects/weirdos.rb +44 -0
- metadata +26 -14
- data/lib/metable.rb +0 -54
- data/lib/metable/class_methods.rb +0 -83
- data/lib/metable/instance_methods.rb +0 -93
data/README
CHANGED
@@ -24,17 +24,17 @@ Mixin comes in handy in following situations:
|
|
24
24
|
(similar to defining a hierarchy of abstract base classes). This includes calls
|
25
25
|
to +super+ to invoke a "super-mixin's" implementation of a given class method.
|
26
26
|
|
27
|
-
* When you wish that certian module methods would get 'inherited' by including
|
28
|
-
modules in the same manner that class methods get inherited by subclasses.
|
29
|
-
|
30
27
|
* When you simply get tired of writing the same old "<tt>def self.inherited(base);
|
31
28
|
base.extend(ClassMethods)</tt>" method (or some variation of it) over and over
|
32
29
|
again, thereby violating the sacred DRY principle ;)
|
33
30
|
|
34
|
-
==
|
31
|
+
== Examples
|
35
32
|
|
36
33
|
require 'mixin'
|
37
34
|
|
35
|
+
|
36
|
+
# Some common uses:
|
37
|
+
|
38
38
|
module FooBase
|
39
39
|
@@foo_class_attr = "FooBase's class attribute"
|
40
40
|
|
@@ -44,6 +44,10 @@ Mixin comes in handy in following situations:
|
|
44
44
|
@@foo_class_attr + " accessed from FooBase's class mixin"
|
45
45
|
end
|
46
46
|
|
47
|
+
def about_foo
|
48
|
+
"Some Base Foo"
|
49
|
+
end
|
50
|
+
|
47
51
|
end
|
48
52
|
end
|
49
53
|
|
@@ -57,6 +61,10 @@ Mixin comes in handy in following situations:
|
|
57
61
|
@@foo_class_attr + " accessed from FooExtended's class mixin"
|
58
62
|
end
|
59
63
|
|
64
|
+
def about_foo
|
65
|
+
super + " Extended"
|
66
|
+
end
|
67
|
+
|
60
68
|
end
|
61
69
|
end
|
62
70
|
|
@@ -67,18 +75,32 @@ Mixin comes in handy in following situations:
|
|
67
75
|
|
68
76
|
FooBar.foo_class_method -> "FooBase's class attribute accessed from FooBase's class mixin"
|
69
77
|
FooBar.another_foo_class_method -> "FooBase's class attribute accessed from FooExtended's class mixin"
|
78
|
+
FooBar.about_foo -> "Some Base Foo Extended"
|
79
|
+
|
80
|
+
|
81
|
+
# Get'n clever:
|
82
|
+
|
83
|
+
module Me
|
84
|
+
class_extend self
|
85
|
+
|
86
|
+
def me
|
87
|
+
self
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class Bob
|
92
|
+
include Me
|
93
|
+
end
|
94
|
+
|
95
|
+
Bob.new.me -> #<Bob:0x801b0a7d0>
|
96
|
+
Bob.me -> Bob
|
97
|
+
|
70
98
|
|
99
|
+
# Get'n meta:
|
71
100
|
|
72
|
-
|
101
|
+
(module Fud; class_mixin; end).inspect -> "#<ClassMixin:Fud>"
|
73
102
|
|
74
|
-
As briefly mentioned above, Mixin also provides a way to define module methods
|
75
|
-
on a mixin that get 'inherited' by including modules, but that are not extended
|
76
|
-
to classes. The semantics for defining such methods are identical to defining
|
77
|
-
class methods via +_class_mixin_+ (see +module_mixin+).
|
78
103
|
|
79
|
-
Also packaged with Mixin is the bonus mixin Metable which provides a fistful
|
80
|
-
of useful metaprogramming-friendly methods such as +alias_singleton_method+ and
|
81
|
-
+define_class_method+.
|
82
104
|
|
83
105
|
== Installation
|
84
106
|
|
data/lib/mixin.rb
CHANGED
@@ -1,32 +1,21 @@
|
|
1
|
-
require 'metable/class_methods'
|
2
|
-
|
3
|
-
|
4
1
|
module Mixin
|
5
|
-
include Metable::InstanceMethods
|
6
|
-
extend Metable::ClassMethods
|
7
|
-
|
8
2
|
|
9
|
-
class
|
10
|
-
include Metable::InstanceMethods
|
3
|
+
class ClassMixin < Module # :nodoc:
|
11
4
|
|
12
5
|
def initialize(mixin)
|
13
|
-
|
14
|
-
|
6
|
+
(class << self; self; end).instance_eval do
|
7
|
+
define_method(:instance_mixin) { mixin }
|
8
|
+
end
|
9
|
+
super() # just in case
|
15
10
|
end
|
16
11
|
|
17
|
-
def
|
18
|
-
|
19
|
-
super
|
12
|
+
def to_s
|
13
|
+
"#<ClassMixin:#{instance_mixin.to_s}>"
|
20
14
|
end
|
21
15
|
|
22
|
-
alias class_eval module_eval
|
23
16
|
end
|
24
17
|
|
25
18
|
|
26
|
-
lazy_attr(:__class_mixin__) { SingletonMixin.new }
|
27
|
-
lazy_attr(:__module_mixin__) { ModuleMixin.new(self) }
|
28
|
-
|
29
|
-
|
30
19
|
# Extends the given modules to the classes that subsequently include the
|
31
20
|
# invoking module or one of its submodules.
|
32
21
|
#
|
@@ -40,15 +29,7 @@ module Mixin
|
|
40
29
|
# end
|
41
30
|
#
|
42
31
|
def class_extend(*modules)
|
43
|
-
class_mixin { include *modules }
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
|
-
# Works like +class_extend+ except that the given modules are instead
|
48
|
-
# extended to the invoking module and the modules that subsequently include
|
49
|
-
# it rather than their including classes.
|
50
|
-
def module_extend(*modules)
|
51
|
-
module_mixin { include *modules }
|
32
|
+
class_mixin { include *modules } # told you
|
52
33
|
end
|
53
34
|
|
54
35
|
|
@@ -86,51 +67,24 @@ module Mixin
|
|
86
67
|
# class_mixin -> <em>module</em>
|
87
68
|
#
|
88
69
|
def class_mixin(&block) # :doc:
|
89
|
-
__class_mixin__.module_eval(&block) if
|
70
|
+
__class_mixin__.module_eval(&block) if block
|
90
71
|
__class_mixin__
|
91
72
|
end
|
92
73
|
|
93
74
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
# end
|
102
|
-
# end
|
103
|
-
#
|
104
|
-
# module Hyper
|
105
|
-
# include Active
|
106
|
-
# end
|
107
|
-
#
|
108
|
-
# class ActiveClass
|
109
|
-
# include Active
|
110
|
-
# end
|
111
|
-
#
|
112
|
-
# Active.active_mixin? -> true
|
113
|
-
# Hyper.active_mixin? -> true
|
114
|
-
# ActiveClass.respond_to?(:active_mixin?) -> false
|
115
|
-
#
|
116
|
-
# :call-seq:
|
117
|
-
# module_mixin { <em>block</em> } -> <em>module</em>
|
118
|
-
# module_mixin -> <em>module</em>
|
119
|
-
#
|
120
|
-
def module_mixin(&block) # :doc:
|
121
|
-
__module_mixin__.module_eval(&block) if block_given?
|
122
|
-
__module_mixin__
|
75
|
+
def __class_mixin__
|
76
|
+
cm = ClassMixin.new(self)
|
77
|
+
(class << self; self; end).module_eval do
|
78
|
+
define_method(:__class_mixin__) { cm }
|
79
|
+
private :__class_mixin__
|
80
|
+
end
|
81
|
+
return cm
|
123
82
|
end
|
124
83
|
|
125
|
-
# Call the DRY Police! ;)
|
126
84
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
submodule.extend __class_mixin__
|
131
|
-
else
|
132
|
-
submodule.module_extend __module_mixin__
|
133
|
-
submodule.class_extend __class_mixin__
|
85
|
+
def included(mixin)
|
86
|
+
unless ClassMixin === self && ClassMixin === mixin
|
87
|
+
Class === mixin ? mixin.extend(__class_mixin__) : mixin.class_extend(__class_mixin__)
|
134
88
|
end
|
135
89
|
super
|
136
90
|
end
|
@@ -139,12 +93,18 @@ end
|
|
139
93
|
|
140
94
|
|
141
95
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
96
|
+
class Module # :nodoc:
|
97
|
+
|
98
|
+
def class_extend(*modules)
|
99
|
+
extend ::Mixin
|
100
|
+
class_extend *modules
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def class_mixin(&block)
|
106
|
+
extend ::Mixin
|
107
|
+
class_mixin &block
|
108
|
+
end
|
109
|
+
|
149
110
|
end
|
150
|
-
Module.class_eval { private :module_mixin, :class_mixin }
|
data/test/mixin_case.rb
CHANGED
@@ -25,31 +25,23 @@ class MixinTest < Test::Unit::TestCase
|
|
25
25
|
def test_respond_to
|
26
26
|
load 'meepers.rb'
|
27
27
|
|
28
|
-
[:
|
29
|
-
meeper_mxns.each { |mxn| assert_respond_to mxn, meth }
|
30
|
-
meeper_clss.each { |cls| assert_no_response cls, meth }
|
31
|
-
end
|
32
|
-
[:meeper_class?, :says].each do |meth|
|
28
|
+
[:meeper?, :meep].each do |meth|
|
33
29
|
meeper_mxns.each { |mxn| assert_no_response mxn, meth }
|
34
30
|
meeper_clss.each { |cls| assert_respond_to cls, meth }
|
35
31
|
end
|
36
32
|
|
37
33
|
meeper_mxns[1..-1].each do |mxn|
|
38
|
-
assert_respond_to mxn, :active?
|
39
34
|
assert_no_response mxn, :active_meeper?
|
40
35
|
end
|
41
36
|
meeper_clss[1..-1].each do |cls|
|
42
|
-
assert_no_response cls, :active?
|
43
37
|
assert_respond_to cls, :active_meeper?
|
44
38
|
end
|
45
|
-
assert_no_response Meeper, :
|
39
|
+
assert_no_response Meeper, :active_meeper?
|
46
40
|
assert_no_response MeeperCls, :active_meeper?
|
47
41
|
|
48
|
-
assert_respond_to HyperMeeper, :hyperactive?
|
49
|
-
assert_no_response HyperMeeperCls, :hyperactive?
|
50
|
-
assert_respond_to HyperMeeperCls, :hyper_meeper?
|
51
42
|
assert_no_response HyperMeeper, :hyper_meeper?
|
52
|
-
|
43
|
+
assert_respond_to HyperMeeperCls, :hyper_meeper?
|
44
|
+
meeper_mxns[0..-2].each { |mxn| assert_no_response mxn, :hyper_meeper? }
|
53
45
|
meeper_clss[0..-2].each { |cls| assert_no_response cls, :hyper_meeper? }
|
54
46
|
end
|
55
47
|
|
@@ -60,15 +52,14 @@ class MixinTest < Test::Unit::TestCase
|
|
60
52
|
assert M.class_variables.empty?
|
61
53
|
assert M.instance_variables.empty?
|
62
54
|
|
63
|
-
[M::
|
55
|
+
[M::ScoperCls, M::XScoperCls].each do |mod|
|
64
56
|
assert_same mod, mod.me
|
65
57
|
assert_same :cls, mod.cls_attr
|
66
58
|
end
|
67
|
-
|
68
|
-
[M::XScoper, M::ScoperCls].each { |mod| assert_nil mod.inst_attr }
|
59
|
+
assert_nil M::ScoperCls.inst_attr
|
69
60
|
assert_same :xinst, M::XScoperCls.inst_attr
|
70
|
-
M::
|
71
|
-
assert_same :woot, M::
|
61
|
+
M::ScoperCls.instance_variable_set :@inst_attr, :woot
|
62
|
+
assert_same :woot, M::ScoperCls.inst_attr
|
72
63
|
end
|
73
64
|
|
74
65
|
|
@@ -77,37 +68,30 @@ class MixinTest < Test::Unit::TestCase
|
|
77
68
|
load 'hopons.rb'
|
78
69
|
|
79
70
|
Meeper.module_eval do
|
80
|
-
module_mixin do
|
81
|
-
def newb
|
82
|
-
:newbie
|
83
|
-
end
|
84
|
-
end
|
85
71
|
class_mixin do
|
86
72
|
def noob
|
87
|
-
:
|
73
|
+
:newbie
|
88
74
|
end
|
89
75
|
end
|
90
76
|
end
|
91
77
|
|
92
|
-
meeper_mxns.each { |mxn| assert_respond_to mxn, :newb }
|
93
78
|
meeper_clss.each { |cls| assert_respond_to cls, :noob }
|
94
79
|
|
95
80
|
Meeper.module_eval do
|
96
81
|
include Duck
|
97
|
-
module_mixin do
|
98
|
-
include Plain
|
99
|
-
end
|
100
82
|
class_mixin do
|
101
83
|
include Plain
|
102
84
|
end
|
103
85
|
end
|
104
86
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
assert_no_response mod, :quack
|
109
|
-
assert_no_response mod, :flavor
|
87
|
+
meeper_clss.each do |cls|
|
88
|
+
assert_no_response cls, :quack
|
89
|
+
assert_no_response cls, :flavor
|
110
90
|
end
|
91
|
+
|
92
|
+
Meepian.send :include, Meeper
|
93
|
+
assert_respond_to Meepian, :quack
|
94
|
+
assert_respond_to Meepian, :flavor
|
111
95
|
end
|
112
96
|
|
113
97
|
|
@@ -115,26 +99,19 @@ class MixinTest < Test::Unit::TestCase
|
|
115
99
|
load 'extenders.rb'
|
116
100
|
load 'hopons.rb'
|
117
101
|
|
118
|
-
assert_same :
|
119
|
-
assert_same :
|
120
|
-
assert_same :
|
121
|
-
assert_same :
|
122
|
-
assert_same :
|
123
|
-
assert_same :
|
124
|
-
assert_same :cls_mxn_ping, Xtended.ping
|
125
|
-
assert_same :cls_mxn_ping, Xtendedr.ping
|
102
|
+
assert_same :xing, Xtended.ping
|
103
|
+
assert_same :pong, Xtended.pong
|
104
|
+
assert_same :nudge, Xtended.nudge
|
105
|
+
assert_same :xing, Xtendedr.ping
|
106
|
+
assert_same :pong, Xtendedr.pong
|
107
|
+
assert_same :nudge, Xtendedr.nudge
|
126
108
|
|
127
|
-
Xtendr.module_extend Plain
|
128
109
|
Xtendr.class_extend Plain
|
129
|
-
|
130
|
-
assert_same :vanilla, Xtendr.flavor
|
131
|
-
assert_no_response Xtendrer, :flavor
|
132
110
|
assert_no_response Xtended, :flavor
|
111
|
+
assert_no_response Xtendedr, :flavor
|
133
112
|
|
134
|
-
xhaustv =
|
135
|
-
xhausted = Class.new { include Xtendr }
|
113
|
+
xhaustv = Class.new { include Xtendr }
|
136
114
|
assert_same :vanilla, xhaustv.flavor
|
137
|
-
assert_same :vanilla, xhausted.flavor
|
138
115
|
end
|
139
116
|
|
140
117
|
|
@@ -142,89 +119,70 @@ class MixinTest < Test::Unit::TestCase
|
|
142
119
|
load 'includers.rb'
|
143
120
|
load 'hopons.rb'
|
144
121
|
|
145
|
-
assert_same :
|
146
|
-
assert_same :
|
147
|
-
assert_same :
|
148
|
-
assert_same :
|
149
|
-
assert_same :
|
150
|
-
assert_same :
|
151
|
-
assert_same :cls_mxn_ping, Included.ping
|
152
|
-
assert_same :cls_mxn_ping, Includedr.ping
|
122
|
+
assert_same :ding, Included.ping
|
123
|
+
assert_same :pong, Included.pong
|
124
|
+
assert_same :nudge, Included.nudge
|
125
|
+
assert_same :ding, Includedr.ping
|
126
|
+
assert_same :pong, Includedr.pong
|
127
|
+
assert_same :nudge, Includedr.nudge
|
153
128
|
|
154
|
-
Includr.module_eval do
|
155
|
-
module_mixin { include Plain }
|
156
|
-
end
|
157
129
|
Includr.module_eval do
|
158
130
|
class_mixin { include Plain }
|
159
131
|
end
|
160
132
|
|
161
|
-
assert_same :vanilla, Includr.flavor
|
162
|
-
assert_no_response Includrer, :flavor
|
163
133
|
assert_no_response Included, :flavor
|
134
|
+
assert_no_response Includedr, :flavor
|
164
135
|
|
165
|
-
xhaustv =
|
166
|
-
xhausted = Class.new { include Includr }
|
136
|
+
xhaustv = Class.new { include Includr }
|
167
137
|
assert_same :vanilla, xhaustv.flavor
|
168
|
-
assert_same :vanilla, xhausted.flavor
|
169
138
|
end
|
170
139
|
|
171
140
|
|
172
141
|
def test_supers
|
173
142
|
load 'soopers.rb'
|
174
143
|
|
175
|
-
assert_equal [0
|
176
|
-
assert_equal [
|
177
|
-
assert_equal [
|
178
|
-
|
179
|
-
assert_equal [1,0], SooprC1.giv_em
|
180
|
-
assert_equal [2,1,0], SooprC2.giv_em
|
181
|
-
assert_equal [3,2,1,0], SooprC3.giv_em
|
182
|
-
|
183
|
-
assert_equal [0,1,2,3,7,9], Soopr4.giv_er
|
184
|
-
assert_equal [666,9,7,3,2,1,0], SooprC4.giv_em
|
144
|
+
assert_equal [1,0], SooprC1.giv_er
|
145
|
+
assert_equal [2,1,0], SooprC2.giv_er
|
146
|
+
assert_equal [3,2,1,0], SooprC3.giv_er
|
147
|
+
assert_equal [666,9,7,3,2,1,0], SooprC4.giv_er
|
185
148
|
end
|
186
149
|
|
187
150
|
|
188
151
|
def test_laziness
|
189
152
|
load 'sleepers.rb'
|
190
153
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
assert SansMxn.
|
154
|
+
assert_kind_of Mixin, LazyExt
|
155
|
+
assert_kind_of Mixin, LazyMxn
|
156
|
+
|
157
|
+
assert SansMxn.public_methods.include?('class_extend')
|
195
158
|
assert SansMxn.private_methods.include?('class_mixin')
|
196
159
|
assert !SansMxn.kind_of?(Mixin)
|
197
160
|
SansMxn.class_extend Module.new
|
198
161
|
assert_kind_of Mixin, SansMxn
|
162
|
+
assert !SansMxn.public_methods.include?('class_mixin')
|
163
|
+
assert !SansMxn.protected_methods.include?('class_mixin')
|
199
164
|
end
|
200
165
|
|
201
166
|
|
202
|
-
def
|
203
|
-
load '
|
167
|
+
def test_tips_and_tricks
|
168
|
+
load 'clevers.rb'
|
204
169
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
true
|
214
|
-
end
|
215
|
-
}
|
216
|
-
end
|
217
|
-
assert Meeper.rico? && Meeper.suave?
|
170
|
+
assert_respond_to Adroit, :trick?
|
171
|
+
assert_respond_to Adroit.new, :technique?
|
172
|
+
|
173
|
+
dcm = Deft.send(:class_mixin)
|
174
|
+
assert_same Deft, dcm.instance_mixin
|
175
|
+
assert_equal "#<ClassMixin:Deft>", dcm.to_s
|
176
|
+
assert_equal "#<ClassMixin:Deft>", dcm.inspect
|
177
|
+
assert_equal "", dcm.name
|
218
178
|
end
|
219
179
|
|
220
180
|
|
221
|
-
def
|
222
|
-
load '
|
181
|
+
def test_weirdos
|
182
|
+
load 'weirdos.rb'
|
223
183
|
|
224
|
-
|
225
|
-
|
226
|
-
assert Deft.technique?
|
227
|
-
assert Adroit.technique?
|
184
|
+
assert_respond_to Epsilon, :cloned?
|
185
|
+
assert_respond_to Brave.new, :world
|
228
186
|
end
|
229
187
|
|
230
188
|
end
|
@@ -1,20 +1,19 @@
|
|
1
1
|
module Clever
|
2
|
-
|
2
|
+
class_extend self
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
true
|
7
|
-
end
|
4
|
+
def trick?
|
5
|
+
true
|
8
6
|
end
|
9
7
|
end
|
10
8
|
|
11
9
|
|
12
10
|
module Deft
|
13
|
-
|
14
|
-
class_extend self
|
11
|
+
include class_mixin
|
15
12
|
|
16
|
-
|
17
|
-
|
13
|
+
class_mixin do
|
14
|
+
def technique?
|
15
|
+
true
|
16
|
+
end
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
@@ -2,18 +2,11 @@ require 'nudgers'
|
|
2
2
|
|
3
3
|
|
4
4
|
module Xtendr
|
5
|
-
|
6
|
-
class_extend ClsNudgr
|
7
|
-
|
8
|
-
module_mixin do
|
9
|
-
def ping
|
10
|
-
:mod_mxn_ping
|
11
|
-
end
|
12
|
-
end
|
5
|
+
class_extend Nudgr
|
13
6
|
|
14
7
|
class_mixin do
|
15
8
|
def ping
|
16
|
-
:
|
9
|
+
:xing
|
17
10
|
end
|
18
11
|
end
|
19
12
|
end
|
@@ -6,23 +6,12 @@ end
|
|
6
6
|
|
7
7
|
|
8
8
|
module Meeper
|
9
|
-
|
10
|
-
module_mixin do
|
11
|
-
def meeper_mixin?
|
12
|
-
true
|
13
|
-
end
|
14
|
-
|
15
|
-
def meep
|
16
|
-
:meep
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
9
|
class_mixin do
|
21
|
-
def
|
10
|
+
def meeper?
|
22
11
|
true
|
23
12
|
end
|
24
13
|
|
25
|
-
def
|
14
|
+
def meep
|
26
15
|
:meep
|
27
16
|
end
|
28
17
|
end
|
@@ -32,12 +21,6 @@ end
|
|
32
21
|
module ActiveMeeper
|
33
22
|
include Meeper
|
34
23
|
|
35
|
-
module_mixin do
|
36
|
-
def active?
|
37
|
-
true
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
24
|
class_mixin do
|
42
25
|
def active_meeper?
|
43
26
|
true
|
@@ -49,12 +32,6 @@ end
|
|
49
32
|
module HyperMeeper
|
50
33
|
include ActiveMeeper
|
51
34
|
|
52
|
-
module_mixin do
|
53
|
-
def hyperactive?
|
54
|
-
true
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
35
|
class_mixin do
|
59
36
|
def hyper_meeper?
|
60
37
|
true
|
@@ -74,3 +51,6 @@ end
|
|
74
51
|
class HyperMeeperCls
|
75
52
|
include HyperMeeper
|
76
53
|
end
|
54
|
+
|
55
|
+
class Meepian
|
56
|
+
end
|
@@ -1,21 +1,17 @@
|
|
1
1
|
module Pingr
|
2
2
|
def ping
|
3
|
-
:
|
3
|
+
:ping
|
4
4
|
end
|
5
|
-
end
|
6
|
-
|
7
5
|
|
8
|
-
|
9
|
-
|
10
|
-
def nudge
|
11
|
-
:module
|
6
|
+
def pong
|
7
|
+
:pong
|
12
8
|
end
|
13
9
|
end
|
14
10
|
|
15
11
|
|
16
|
-
module
|
12
|
+
module Nudgr
|
17
13
|
include Pingr
|
18
14
|
def nudge
|
19
|
-
:
|
15
|
+
:nudge
|
20
16
|
end
|
21
17
|
end
|
@@ -1,18 +1,10 @@
|
|
1
1
|
module SansMxn
|
2
2
|
end
|
3
3
|
|
4
|
-
module
|
5
|
-
module_extend SansMxn
|
6
|
-
end
|
7
|
-
|
8
|
-
module LazyClsExt
|
4
|
+
module LazyExt
|
9
5
|
class_extend SansMxn
|
10
6
|
end
|
11
7
|
|
12
|
-
module
|
13
|
-
module_mixin {}
|
14
|
-
end
|
15
|
-
|
16
|
-
module LazyClsMxn
|
8
|
+
module LazyMxn
|
17
9
|
class_mixin {}
|
18
10
|
end
|
@@ -1,29 +1,15 @@
|
|
1
|
-
module
|
1
|
+
module Sooprb
|
2
2
|
def giv_er
|
3
3
|
[0]
|
4
4
|
end
|
5
5
|
end
|
6
6
|
|
7
|
-
module SooprCX
|
8
|
-
def giv_em
|
9
|
-
[0]
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
7
|
|
14
8
|
module Soopr1
|
15
|
-
|
16
|
-
|
17
|
-
module_mixin do
|
18
|
-
def giv_er
|
19
|
-
super + [1]
|
20
|
-
end
|
21
|
-
end
|
9
|
+
class_extend Sooprb
|
22
10
|
|
23
11
|
class_mixin do
|
24
|
-
|
25
|
-
|
26
|
-
def giv_em
|
12
|
+
def giv_er
|
27
13
|
[1] + super
|
28
14
|
end
|
29
15
|
end
|
@@ -33,14 +19,8 @@ end
|
|
33
19
|
module Soopr2
|
34
20
|
include Soopr1
|
35
21
|
|
36
|
-
module_mixin do
|
37
|
-
def giv_er
|
38
|
-
super + [2]
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
22
|
class_mixin do
|
43
|
-
def
|
23
|
+
def giv_er
|
44
24
|
[2] + super
|
45
25
|
end
|
46
26
|
end
|
@@ -50,14 +30,8 @@ end
|
|
50
30
|
module Soopr3
|
51
31
|
include Soopr2
|
52
32
|
|
53
|
-
module_mixin do
|
54
|
-
def giv_er
|
55
|
-
super + [3]
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
33
|
class_mixin do
|
60
|
-
def
|
34
|
+
def giv_er
|
61
35
|
[3] + super
|
62
36
|
end
|
63
37
|
end
|
@@ -78,14 +52,8 @@ end
|
|
78
52
|
|
79
53
|
|
80
54
|
|
81
|
-
module
|
55
|
+
module DooprX
|
82
56
|
def giv_er
|
83
|
-
super + [7]
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
module DooprCX
|
88
|
-
def giv_em
|
89
57
|
[7] + super
|
90
58
|
end
|
91
59
|
end
|
@@ -93,19 +61,12 @@ end
|
|
93
61
|
|
94
62
|
module Soopr4
|
95
63
|
include Soopr3
|
96
|
-
class_extend DooprCX
|
97
64
|
|
98
65
|
class_mixin do
|
99
|
-
|
100
|
-
[9] + super
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
module_mixin do
|
105
|
-
include DooprMX
|
66
|
+
include DooprX
|
106
67
|
|
107
68
|
def giv_er
|
108
|
-
|
69
|
+
[9] + super
|
109
70
|
end
|
110
71
|
end
|
111
72
|
end
|
@@ -114,7 +75,7 @@ end
|
|
114
75
|
class SooprC4
|
115
76
|
include Soopr4
|
116
77
|
|
117
|
-
def self.
|
78
|
+
def self.giv_er
|
118
79
|
[666] + super
|
119
80
|
end
|
120
81
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# A mixin includes a class_mixin
|
2
|
+
# A class_mixin includes a mixin
|
3
|
+
# A class_mixin has a class_mixin
|
4
|
+
|
5
|
+
module Bokanovsky
|
6
|
+
class_mixin do
|
7
|
+
class_mixin do
|
8
|
+
def cloned?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
class Epsilon
|
17
|
+
include Bokanovsky.send(:class_mixin)
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
module Infantilism
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
module Hypnopaedia
|
27
|
+
class_mixin # pull in Mixin
|
28
|
+
Infantilism.class_extend self
|
29
|
+
|
30
|
+
def world
|
31
|
+
:hello
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
module Soma
|
37
|
+
class_mixin
|
38
|
+
include Infantilism.send(:class_mixin)
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
class Brave
|
43
|
+
include Soma
|
44
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mixin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Hersch Stevenson (xian)
|
@@ -9,11 +15,11 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date:
|
18
|
+
date: 2011-03-09 00:00:00 -08:00
|
13
19
|
default_executable:
|
14
20
|
dependencies: []
|
15
21
|
|
16
|
-
description:
|
22
|
+
description: Mixins made classier!
|
17
23
|
email: stevenson@persapient.com
|
18
24
|
executables: []
|
19
25
|
|
@@ -23,48 +29,54 @@ extra_rdoc_files:
|
|
23
29
|
- README
|
24
30
|
- LICENSE
|
25
31
|
files:
|
26
|
-
- lib/metable/instance_methods.rb
|
27
|
-
- lib/metable/class_methods.rb
|
28
32
|
- lib/mixin.rb
|
29
|
-
- lib/metable.rb
|
30
33
|
- test/mixin_case.rb
|
34
|
+
- test/test_subjects/clevers.rb
|
31
35
|
- test/test_subjects/extenders.rb
|
32
|
-
- test/test_subjects/scopers.rb
|
33
36
|
- test/test_subjects/hopons.rb
|
37
|
+
- test/test_subjects/includers.rb
|
34
38
|
- test/test_subjects/meepers.rb
|
35
39
|
- test/test_subjects/nudgers.rb
|
36
|
-
- test/test_subjects/
|
37
|
-
- test/test_subjects/soopers.rb
|
40
|
+
- test/test_subjects/scopers.rb
|
38
41
|
- test/test_subjects/sleepers.rb
|
39
|
-
- test/test_subjects/
|
42
|
+
- test/test_subjects/soopers.rb
|
43
|
+
- test/test_subjects/weirdos.rb
|
40
44
|
- README
|
41
45
|
- LICENSE
|
42
46
|
- Rakefile
|
43
47
|
has_rdoc: true
|
44
48
|
homepage: http://api.persapient.com/mixin
|
49
|
+
licenses: []
|
50
|
+
|
45
51
|
post_install_message:
|
46
52
|
rdoc_options: []
|
47
53
|
|
48
54
|
require_paths:
|
49
55
|
- lib
|
50
56
|
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
51
58
|
requirements:
|
52
59
|
- - ">="
|
53
60
|
- !ruby/object:Gem::Version
|
61
|
+
hash: 3
|
62
|
+
segments:
|
63
|
+
- 0
|
54
64
|
version: "0"
|
55
|
-
version:
|
56
65
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
57
67
|
requirements:
|
58
68
|
- - ">="
|
59
69
|
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
60
73
|
version: "0"
|
61
|
-
version:
|
62
74
|
requirements: []
|
63
75
|
|
64
76
|
rubyforge_project: mixin
|
65
|
-
rubygems_version: 1.
|
77
|
+
rubygems_version: 1.6.2
|
66
78
|
signing_key:
|
67
|
-
specification_version:
|
79
|
+
specification_version: 3
|
68
80
|
summary: An extention to Module that is intended to ease the development of mixins that involve both class and instance methods.
|
69
81
|
test_files:
|
70
82
|
- test/mixin_case.rb
|
data/lib/metable.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
require 'mixin'
|
2
|
-
|
3
|
-
|
4
|
-
# == Metable - The Bonus Mixin
|
5
|
-
#
|
6
|
-
# Metable is a mixin that provides a bundle of handy methods for the aspiring
|
7
|
-
# ruby metaprogrammer.
|
8
|
-
#
|
9
|
-
# Have you ever wanted an easy way to alias a class method? Check out
|
10
|
-
# +alias_class_method+. Have you ever desired a clean way to dynamically define
|
11
|
-
# a class method in the same manner you would an instance method using
|
12
|
-
# +define_method+ ? Well feast your eyes on +define_class_method+. In fact, you can
|
13
|
-
# dynamically define a singleton method on any object the same way with
|
14
|
-
# +define_singleton_method+.
|
15
|
-
#
|
16
|
-
# Metable provides those and many more (see the full list bellow).
|
17
|
-
#
|
18
|
-
# === Public Instance Methods
|
19
|
-
# * eigen_eval
|
20
|
-
# * eigenclass <em>(aliased as metaclass)</em>
|
21
|
-
# * private_singleton_method
|
22
|
-
# * protected_singleton_method
|
23
|
-
# * public_singleton_method
|
24
|
-
#
|
25
|
-
# === Private Instance Methods
|
26
|
-
# * alias_singleton_method
|
27
|
-
# * define_singleton_method <em>(aliased as define_public_singleton_method)</em>
|
28
|
-
# * define_private_singleton_method
|
29
|
-
# * define_protected_singleton_method
|
30
|
-
#
|
31
|
-
# === Public Module Mixin & Class Mixin Methods
|
32
|
-
# * class_method_defined?
|
33
|
-
# * eigen_eval
|
34
|
-
# * eigenclass <em>(aliased as metaclass)</em>
|
35
|
-
# * private_class_method_defined?
|
36
|
-
# * private_singleton_method
|
37
|
-
# * protected_class_method
|
38
|
-
# * protected_class_method_defined?
|
39
|
-
# * protected_singleton_method <em>(aliased as protected_class_method)</em>
|
40
|
-
# * public_class_method_defined?
|
41
|
-
# * public_singleton_method
|
42
|
-
#
|
43
|
-
# === Private Module Mixin & Class Mixin Methods
|
44
|
-
# * alias_singleton_method <em>(aliased as alias_class_method)</em>
|
45
|
-
# * define_singleton_method <em>(aliased as define_class_method, define_public_class_method, define_public_singleton_method)</em>
|
46
|
-
# * define_private_singleton_method <em>(aliased as define_private_class_method)</em>
|
47
|
-
# * define_protected_singleton_method <em>(aliased as define_protected_class_method)</em>
|
48
|
-
# * lazy_attr
|
49
|
-
#
|
50
|
-
module Metable
|
51
|
-
include Metable::InstanceMethods
|
52
|
-
class_extend Metable::ClassMethods
|
53
|
-
module_extend Metable::ClassMethods
|
54
|
-
end
|
@@ -1,83 +0,0 @@
|
|
1
|
-
require 'metable/instance_methods'
|
2
|
-
|
3
|
-
|
4
|
-
module Metable
|
5
|
-
module ClassMethods
|
6
|
-
include InstanceMethods
|
7
|
-
|
8
|
-
# Returns +true+ if the named class method is defined by the invoking class
|
9
|
-
# (or its extended modules or ancestors). Public and protected (yes,
|
10
|
-
# _protected_) class methods are matched.
|
11
|
-
def class_method_defined?(method_name)
|
12
|
-
eigenclass.method_defined? method_name
|
13
|
-
end
|
14
|
-
|
15
|
-
# Returns +true+ if the named public class method is defined by the invoking
|
16
|
-
# class (or its extended modules or ancestors).
|
17
|
-
def public_class_method_defined?(method_name)
|
18
|
-
eigenclass.public_method_defined? method_name
|
19
|
-
end
|
20
|
-
|
21
|
-
# Returns +true+ if the named protected class method is defined by the invoking
|
22
|
-
# class (or its extended modules or ancestors).
|
23
|
-
def protected_class_method_defined?(method_name)
|
24
|
-
eigenclass.protected_method_defined? method_name
|
25
|
-
end
|
26
|
-
|
27
|
-
# Returns +true+ if the named private class method is defined by the invoking
|
28
|
-
# class (or its extended modules or ancestors).
|
29
|
-
def private_class_method_defined?(method_name)
|
30
|
-
eigenclass.private_method_defined? method_name
|
31
|
-
end
|
32
|
-
|
33
|
-
|
34
|
-
alias protected_class_method protected_singleton_method
|
35
|
-
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
alias alias_class_method alias_singleton_method
|
40
|
-
|
41
|
-
alias define_class_method define_singleton_method
|
42
|
-
alias define_public_class_method define_singleton_method
|
43
|
-
alias define_protected_class_method define_protected_singleton_method
|
44
|
-
alias define_private_class_method define_private_singleton_method
|
45
|
-
|
46
|
-
|
47
|
-
# Defines an instance method for _name_ which evaluates the _thunk_ the
|
48
|
-
# first time it is invoked on a given instance and returns the resulting
|
49
|
-
# object, and then returns that same object on each subsequent call. The
|
50
|
-
# _thunk_ block is evaluated within the context of the invoking instance
|
51
|
-
# object using +instance_eval+.
|
52
|
-
#
|
53
|
-
# The _access_ argument can be a symbol or string representing the access
|
54
|
-
# level for the defined method (public, private, or protected). The default
|
55
|
-
# access level is +private+.
|
56
|
-
#
|
57
|
-
# class Foo
|
58
|
-
# include Metable
|
59
|
-
# lazy_attr(:time_of_evaluation, :public) { Time.now }
|
60
|
-
# end
|
61
|
-
#
|
62
|
-
# foo = Foo.new
|
63
|
-
# sleep 7
|
64
|
-
# Time.now -> Fri Sep 05 16:20:00 -0700 2008
|
65
|
-
# foo.time_of_evaluation -> Fri Sep 05 16:20:00 -0700 2008
|
66
|
-
# sleep 86407
|
67
|
-
# foo.time_of_evaluation -> Fri Sep 05 16:20:00 -0700 2008
|
68
|
-
# foo.instance_variables -> []
|
69
|
-
#
|
70
|
-
def lazy_attr(name, access = :private, &thunk) # :doc:
|
71
|
-
define_method name do
|
72
|
-
result = instance_eval &thunk
|
73
|
-
eigen_eval do
|
74
|
-
method_defined?(name) && undef_method(name)
|
75
|
-
define_method(name) { result } && __send__(access, name)
|
76
|
-
end
|
77
|
-
result
|
78
|
-
end
|
79
|
-
__send__ access, name
|
80
|
-
end
|
81
|
-
|
82
|
-
end
|
83
|
-
end
|
@@ -1,93 +0,0 @@
|
|
1
|
-
module Metable
|
2
|
-
module InstanceMethods
|
3
|
-
|
4
|
-
# Returns the invoking object's eigenclass.
|
5
|
-
def eigenclass
|
6
|
-
class << self
|
7
|
-
self
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
alias metaclass eigenclass
|
12
|
-
|
13
|
-
|
14
|
-
# Evaluates a string containing Ruby source code, or the given block within
|
15
|
-
# the context of the invoking object's eigenclass.
|
16
|
-
#
|
17
|
-
# <tt>_obj_.eigen_eval { _block_ }</tt> would be equivalent to
|
18
|
-
# <tt>_obj_.eigenclass.instance_eval { _block_ }</tt>
|
19
|
-
#
|
20
|
-
# :call-seq:
|
21
|
-
# eigen_eval(<em>string</em> <, <em>file</em> <, <em>line</em>>>) -> <em>other_obj</em>
|
22
|
-
# eigen_eval { <em>block</em> } -> <em>other_obj</em>
|
23
|
-
#
|
24
|
-
def eigen_eval(*args, &block)
|
25
|
-
eigenclass.instance_eval(*args, &block)
|
26
|
-
end
|
27
|
-
|
28
|
-
|
29
|
-
# Makes the invoking object's existing singleton methods private.
|
30
|
-
def private_singleton_method(*method_ids)
|
31
|
-
eigen_eval { private *method_ids }
|
32
|
-
end
|
33
|
-
|
34
|
-
# Makes the invoking object's existing singleton methods protected.
|
35
|
-
def protected_singleton_method(*method_ids)
|
36
|
-
eigen_eval { protected *method_ids }
|
37
|
-
end
|
38
|
-
|
39
|
-
# Makes the invoking object's existing singleton methods public.
|
40
|
-
def public_singleton_method(*method_ids)
|
41
|
-
eigen_eval { public *method_ids }
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
# Makes _new_id_ an alias of the singleton method _old_id_ within the
|
48
|
-
# invoking object.
|
49
|
-
def alias_singleton_method(new_id, old_id) # :doc:
|
50
|
-
eigen_eval { alias_method new_id, old_id }
|
51
|
-
end
|
52
|
-
|
53
|
-
# Defines a public singleton method on the invoking object (similar to
|
54
|
-
# +define_method+).
|
55
|
-
#
|
56
|
-
# <em>Aliased as</em> +define_public_singleton_method+
|
57
|
-
#
|
58
|
-
# :call-seq:
|
59
|
-
# define_singleton_method(<em>symbol</em>, <em>method</em>) -> <em>method</em>
|
60
|
-
# define_singleton_method(<em>symbol</em>) { <em>block</em> } -> <em>proc</em>
|
61
|
-
#
|
62
|
-
def define_singleton_method(*args, &block) # :doc:
|
63
|
-
eigen_eval { define_method(*args, &block) }
|
64
|
-
end
|
65
|
-
|
66
|
-
alias define_public_singleton_method define_singleton_method # :doc:
|
67
|
-
|
68
|
-
# Defines a private singleton method on the invoking object (similar to
|
69
|
-
# +define_method+).
|
70
|
-
#
|
71
|
-
# :call-seq:
|
72
|
-
# define_private_singleton_method(<em>symbol</em>, <em>method</em>) -> <em>method</em>
|
73
|
-
# define_private_singleton_method(<em>symbol</em>) { <em>block</em> } -> <em>proc</em>
|
74
|
-
#
|
75
|
-
def define_private_singleton_method(*args, &block) # :doc:
|
76
|
-
define_singleton_method(*args, &block)
|
77
|
-
private_singleton_method(args.first)
|
78
|
-
end
|
79
|
-
|
80
|
-
# Defines a protected singleton method on the invoking object (similar to
|
81
|
-
# +define_method+).
|
82
|
-
#
|
83
|
-
# :call-seq:
|
84
|
-
# define_protected_singleton_method(<em>symbol</em>, <em>method</em>) -> <em>method</em>
|
85
|
-
# define_protected_singleton_method(<em>symbol</em>) { <em>block</em> } -> <em>proc</em>
|
86
|
-
#
|
87
|
-
def define_protected_singleton_method(*args, &block) # :doc:
|
88
|
-
define_singleton_method(*args, &block)
|
89
|
-
protected_singleton_method(args.first)
|
90
|
-
end
|
91
|
-
|
92
|
-
end
|
93
|
-
end
|