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 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
- == Example
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
- == Extra Stuff
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
 
@@ -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 ModuleMixin < SingletonMixin = Class.new(Module) # :nodoc:
10
- include Metable::InstanceMethods
3
+ class ClassMixin < Module # :nodoc:
11
4
 
12
5
  def initialize(mixin)
13
- define_private_singleton_method(:mixin) { mixin }
14
- super()
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 module_eval(*args, &block)
18
- mixin.eigenclass.module_eval *args, &block
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 block_given?
70
+ __class_mixin__.module_eval(&block) if block
90
71
  __class_mixin__
91
72
  end
92
73
 
93
74
 
94
- # Works the same as +class_mixin+ except that the invoking module's
95
- # +module_mixin+ is instead extended to the invoking module itself rather
96
- # than its including classes.
97
- #
98
- # module Active
99
- # module_mixin do
100
- # def active_mixin?; true; end
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
- def included(submodule)
129
- if submodule.kind_of?(Class) || submodule.kind_of?(SingletonMixin)
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
- [:module_mixin, :module_extend, :class_mixin, :class_extend].each do |name|
143
- Module.class_eval %Q{
144
- def #{name}(*args, &block)
145
- extend ::Mixin
146
- send :#{name}, *args, &block
147
- end
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 }
@@ -25,31 +25,23 @@ class MixinTest < Test::Unit::TestCase
25
25
  def test_respond_to
26
26
  load 'meepers.rb'
27
27
 
28
- [:meeper_mixin?, :meep].each do |meth|
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, :active
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
- meeper_mxns[0..-2].each { |mxn| assert_no_response mxn, :hyperactive? }
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::Scoper, M::XScoper, M::ScoperCls, M::XScoperCls].each do |mod|
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
- assert_same :inst, M::Scoper.inst_attr
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::XScoper.instance_variable_set :@inst_attr, :woot
71
- assert_same :woot, M::XScoper.inst_attr
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
- :nooby
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
- assert_respond_to Meeper, :quack
106
- assert_respond_to Meeper, :flavor
107
- (meeper_mxns[1..-1] + meeper_clss).each do |mod|
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 :module, Xtendr.nudge
119
- assert_same :module, Xtendrer.nudge
120
- assert_same :class, Xtended.nudge
121
- assert_same :class, Xtendedr.nudge
122
- assert_same :mod_mxn_ping, Xtendr.ping
123
- assert_same :mod_mxn_ping, Xtendrer.ping
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 = Module.new { include Xtendr }
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 :module, Includr.nudge
146
- assert_same :module, Includrer.nudge
147
- assert_same :class, Included.nudge
148
- assert_same :class, Includedr.nudge
149
- assert_same :mod_mxn_ping, Includr.ping
150
- assert_same :mod_mxn_ping, Includrer.ping
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 = Module.new { include Includr }
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,1], Soopr1.giv_er
176
- assert_equal [0,1,2], Soopr2.giv_er
177
- assert_equal [0,1,2,3], Soopr3.giv_er
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
- [LazyModExt, LazyClsExt, LazyModMxn, LazyClsMxn].each do |mxn|
192
- assert_kind_of Mixin, mxn
193
- end
194
- assert SansMxn.private_methods.include?('module_mixin')
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 test_module_mixin_module_eval
203
- load 'meepers.rb'
167
+ def test_tips_and_tricks
168
+ load 'clevers.rb'
204
169
 
205
- Meeper.module_eval do
206
- module_mixin.module_eval do
207
- def rico?
208
- true
209
- end
210
- end
211
- module_mixin.class_eval %Q{
212
- def suave?
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 test_tips_and_tricks
222
- load 'clevers.rb'
181
+ def test_weirdos
182
+ load 'weirdos.rb'
223
183
 
224
- assert Clever.trick?
225
- assert Adroit.trick?
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
- module_extend class_mixin
2
+ class_extend self
3
3
 
4
- class_mixin do
5
- def trick?
6
- true
7
- end
4
+ def trick?
5
+ true
8
6
  end
9
7
  end
10
8
 
11
9
 
12
10
  module Deft
13
- module_extend self
14
- class_extend self
11
+ include class_mixin
15
12
 
16
- def technique?
17
- true
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
- module_extend ModNudgr
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
- :cls_mxn_ping
9
+ :xing
17
10
  end
18
11
  end
19
12
  end
@@ -1,13 +1,7 @@
1
1
  module Duck
2
- module_mixin do
3
- def quack
4
- :mod_quack
5
- end
6
- end
7
-
8
2
  class_mixin do
9
3
  def quack
10
- :cls_quack
4
+ :quack
11
5
  end
12
6
  end
13
7
  end
@@ -2,19 +2,11 @@ require 'nudgers'
2
2
 
3
3
 
4
4
  module Includr
5
- module_mixin do
6
- include ModNudgr
7
-
8
- def ping
9
- :mod_mxn_ping
10
- end
11
- end
12
-
13
5
  class_mixin do
14
- include ClsNudgr
6
+ include Nudgr
15
7
 
16
8
  def ping
17
- :cls_mxn_ping
9
+ :ding
18
10
  end
19
11
  end
20
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 meeper_class?
10
+ def meeper?
22
11
  true
23
12
  end
24
13
 
25
- def says
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
- :mod_ping
3
+ :ping
4
4
  end
5
- end
6
-
7
5
 
8
- module ModNudgr
9
- include Pingr
10
- def nudge
11
- :module
6
+ def pong
7
+ :pong
12
8
  end
13
9
  end
14
10
 
15
11
 
16
- module ClsNudgr
12
+ module Nudgr
17
13
  include Pingr
18
14
  def nudge
19
- :class
15
+ :nudge
20
16
  end
21
17
  end
@@ -4,20 +4,6 @@ module M
4
4
  @@cls_attr = :cls
5
5
  @inst_attr = :inst
6
6
 
7
- module_mixin do
8
- def cls_attr
9
- @@cls_attr
10
- end
11
-
12
- def inst_attr
13
- @inst_attr
14
- end
15
-
16
- def me
17
- self
18
- end
19
- end
20
-
21
7
  class_mixin do
22
8
  def cls_attr
23
9
  @@cls_attr
@@ -1,18 +1,10 @@
1
1
  module SansMxn
2
2
  end
3
3
 
4
- module LazyModExt
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 LazyModMxn
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 SooprMX
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
- module_extend SooprMX
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
- include SooprCX
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 giv_em
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 giv_em
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 DooprMX
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
- def giv_em
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
- super + [9]
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.giv_em
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
- version: 0.7.1
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: 2008-10-11 00:00:00 -07:00
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/includers.rb
37
- - test/test_subjects/soopers.rb
40
+ - test/test_subjects/scopers.rb
38
41
  - test/test_subjects/sleepers.rb
39
- - test/test_subjects/clevers.rb
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.0.1
77
+ rubygems_version: 1.6.2
66
78
  signing_key:
67
- specification_version: 2
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
@@ -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