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 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