mixin 0.7.1 → 1.0.0
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/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
|