mixin 0.4.1 → 0.7.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 +94 -3
- data/lib/metable.rb +10 -19
- data/lib/mixin.rb +7 -10
- data/test/mixin_case.rb +3 -3
- data/test/test_subjects/clevers.rb +3 -3
- data/test/test_subjects/extenders.rb +2 -2
- data/test/test_subjects/sleepers.rb +2 -2
- data/test/test_subjects/soopers.rb +2 -2
- metadata +8 -8
data/README
CHANGED
@@ -1,6 +1,97 @@
|
|
1
|
-
Mixin
|
1
|
+
= Mixin - mixins made classier.
|
2
2
|
|
3
|
-
|
3
|
+
Mixin extends Ruby's +Module+ class with a small, yet powerful set of features
|
4
|
+
that make the experience of writing mixins more like that of writing classes
|
5
|
+
when it comes to defining class methods.
|
4
6
|
|
7
|
+
Typically, the way to implement a mixin that defines class methods for its
|
8
|
+
includees (at least that I have noticed) is to define a module within the mixin
|
9
|
+
module, usually called +ClassMethods+, which gets automatically extended to an
|
10
|
+
including class by overwriting the mixin's +inherited+ method. This technique
|
11
|
+
is usually sufficient for most situations, but it has a few limitations. One of
|
12
|
+
these is the fact that class attributes referenced in +ClassMethods+ do not
|
13
|
+
exist in the same scope as the enclosing mixin's class attributes.
|
5
14
|
|
6
|
-
|
15
|
+
=== When to use it
|
16
|
+
|
17
|
+
Mixin comes in handy in following situations:
|
18
|
+
|
19
|
+
* When you are writing a mixin with class methods that need to access class
|
20
|
+
attributes defined within the mixin module.
|
21
|
+
|
22
|
+
* When you want to define a "sub-mixin" module which includes another mixin
|
23
|
+
in order to expand upon its class methods in addition to its instance methods
|
24
|
+
(similar to defining a hierarchy of abstract base classes). This includes calls
|
25
|
+
to +super+ to invoke a "super-mixin's" implementation of a given class method.
|
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
|
+
* When you simply get tired of writing the same old "<tt>def self.inherited(base);
|
31
|
+
base.extend(ClassMethods)</tt>" method (or some variation of it) over and over
|
32
|
+
again, thereby violating the sacred DRY principle ;)
|
33
|
+
|
34
|
+
== Example
|
35
|
+
|
36
|
+
require 'mixin'
|
37
|
+
|
38
|
+
module FooBase
|
39
|
+
@@foo_class_attr = "FooBase's class attribute"
|
40
|
+
|
41
|
+
class_mixin do
|
42
|
+
|
43
|
+
def foo_class_method
|
44
|
+
@@foo_class_attr + " accessed from FooBase's class mixin"
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
module FooExtended
|
52
|
+
include FooBase
|
53
|
+
|
54
|
+
class_mixin do
|
55
|
+
|
56
|
+
def another_foo_class_method
|
57
|
+
@@foo_class_attr + " accessed from FooExtended's class mixin"
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
class FooBar
|
65
|
+
include FooExtended
|
66
|
+
end
|
67
|
+
|
68
|
+
FooBar.foo_class_method -> "FooBase's class attribute accessed from FooBase's class mixin"
|
69
|
+
FooBar.another_foo_class_method -> "FooBase's class attribute accessed from FooExtended's class mixin"
|
70
|
+
|
71
|
+
|
72
|
+
== Extra Stuff
|
73
|
+
|
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
|
+
|
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
|
+
|
83
|
+
== Installation
|
84
|
+
|
85
|
+
% sudo gem install mixin
|
86
|
+
|
87
|
+
== License[link://files/LICENSE.html]
|
88
|
+
|
89
|
+
Copyright (c) 2008 Christian Herschel Stevenson, Persapient Systems. Released
|
90
|
+
under the same license[link://files/LICENSE.html] as Ruby.
|
91
|
+
|
92
|
+
== Support
|
93
|
+
|
94
|
+
You're pretty much looking at it.
|
95
|
+
|
96
|
+
For more information, contact mailto:stevenson@persapient.com. This documentation
|
97
|
+
can be found online at http://api.persapient.com/mixin
|
data/lib/metable.rb
CHANGED
@@ -17,43 +17,34 @@ require 'mixin'
|
|
17
17
|
#
|
18
18
|
# === Public Instance Methods
|
19
19
|
# * eigen_eval
|
20
|
-
# * eigenclass
|
21
|
-
# * metaclass
|
20
|
+
# * eigenclass <em>(aliased as metaclass)</em>
|
22
21
|
# * private_singleton_method
|
23
22
|
# * protected_singleton_method
|
24
23
|
# * public_singleton_method
|
25
24
|
#
|
26
25
|
# === Private Instance Methods
|
27
26
|
# * alias_singleton_method
|
28
|
-
# * define_singleton_method
|
27
|
+
# * define_singleton_method <em>(aliased as define_public_singleton_method)</em>
|
29
28
|
# * define_private_singleton_method
|
30
29
|
# * define_protected_singleton_method
|
31
|
-
# * define_public_singleton_method
|
32
30
|
#
|
33
31
|
# === Public Module Mixin & Class Mixin Methods
|
34
32
|
# * class_method_defined?
|
35
33
|
# * eigen_eval
|
36
|
-
# * eigenclass
|
37
|
-
# * metaclass
|
34
|
+
# * eigenclass <em>(aliased as metaclass)</em>
|
38
35
|
# * private_class_method_defined?
|
39
36
|
# * private_singleton_method
|
40
37
|
# * protected_class_method
|
41
38
|
# * protected_class_method_defined?
|
42
|
-
# * protected_singleton_method
|
39
|
+
# * protected_singleton_method <em>(aliased as protected_class_method)</em>
|
43
40
|
# * public_class_method_defined?
|
44
41
|
# * public_singleton_method
|
45
42
|
#
|
46
43
|
# === Private Module Mixin & Class Mixin Methods
|
47
|
-
# * alias_class_method
|
48
|
-
# *
|
49
|
-
# *
|
50
|
-
# *
|
51
|
-
# * define_private_class_method
|
52
|
-
# * define_private_singleton_method
|
53
|
-
# * define_protected_class_method
|
54
|
-
# * define_protected_singleton_method
|
55
|
-
# * define_public_class_method
|
56
|
-
# * define_public_singleton_method
|
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>
|
57
48
|
# * enclosed_attr
|
58
49
|
# * private_enclosure
|
59
50
|
# * protected_enclosure
|
@@ -61,6 +52,6 @@ require 'mixin'
|
|
61
52
|
#
|
62
53
|
module Metable
|
63
54
|
include Metable::InstanceMethods
|
64
|
-
|
65
|
-
|
55
|
+
class_extend Metable::ClassMethods
|
56
|
+
module_extend Metable::ClassMethods
|
66
57
|
end
|
data/lib/mixin.rb
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
require 'metable/class_methods'
|
2
2
|
|
3
3
|
|
4
|
-
# Mixin is an extension to +Module+ that is intended to ease the development
|
5
|
-
# of mixins that involve both class and instance methods.
|
6
|
-
#
|
7
4
|
module Mixin
|
8
5
|
include Metable::InstanceMethods
|
9
6
|
extend Metable::ClassMethods
|
@@ -33,7 +30,7 @@ module Mixin
|
|
33
30
|
# Extends the given modules to the classes that subsequently include the
|
34
31
|
# invoking module or one of its submodules.
|
35
32
|
#
|
36
|
-
# Calling <tt>SomeMixin.
|
33
|
+
# Calling <tt>SomeMixin.class_extend(SomeClassMethods)</tt>
|
37
34
|
# would be equivalent to:
|
38
35
|
#
|
39
36
|
# module SomeMixin
|
@@ -42,15 +39,15 @@ module Mixin
|
|
42
39
|
# end
|
43
40
|
# end
|
44
41
|
#
|
45
|
-
def
|
42
|
+
def class_extend(*modules)
|
46
43
|
class_mixin { include *modules }
|
47
44
|
end
|
48
45
|
|
49
46
|
|
50
|
-
# Works like +
|
47
|
+
# Works like +class_extend+ except that the given modules are instead
|
51
48
|
# extended to the invoking module and the modules that subsequently include
|
52
49
|
# it rather than their including classes.
|
53
|
-
def
|
50
|
+
def module_extend(*modules)
|
54
51
|
module_mixin { include *modules }
|
55
52
|
end
|
56
53
|
|
@@ -132,8 +129,8 @@ module Mixin
|
|
132
129
|
if submodule.kind_of?(Class) || submodule.kind_of?(SingletonMixin)
|
133
130
|
submodule.extend __class_mixin__
|
134
131
|
else
|
135
|
-
submodule.
|
136
|
-
submodule.
|
132
|
+
submodule.module_extend __module_mixin__
|
133
|
+
submodule.class_extend __class_mixin__
|
137
134
|
end
|
138
135
|
super
|
139
136
|
end
|
@@ -142,7 +139,7 @@ end
|
|
142
139
|
|
143
140
|
|
144
141
|
|
145
|
-
[:module_mixin, :
|
142
|
+
[:module_mixin, :module_extend, :class_mixin, :class_extend].each do |name|
|
146
143
|
Module.class_eval %Q{
|
147
144
|
def #{name}(*args, &block)
|
148
145
|
extend ::Mixin
|
data/test/mixin_case.rb
CHANGED
@@ -124,8 +124,8 @@ class MixinTest < Test::Unit::TestCase
|
|
124
124
|
assert_same :cls_mxn_ping, Xtended.ping
|
125
125
|
assert_same :cls_mxn_ping, Xtendedr.ping
|
126
126
|
|
127
|
-
Xtendr.
|
128
|
-
Xtendr.
|
127
|
+
Xtendr.module_extend Plain
|
128
|
+
Xtendr.class_extend Plain
|
129
129
|
|
130
130
|
assert_same :vanilla, Xtendr.flavor
|
131
131
|
assert_no_response Xtendrer, :flavor
|
@@ -194,7 +194,7 @@ class MixinTest < Test::Unit::TestCase
|
|
194
194
|
assert SansMxn.private_methods.include?('module_mixin')
|
195
195
|
assert SansMxn.private_methods.include?('class_mixin')
|
196
196
|
assert !SansMxn.kind_of?(Mixin)
|
197
|
-
SansMxn.
|
197
|
+
SansMxn.class_extend Module.new
|
198
198
|
assert_kind_of Mixin, SansMxn
|
199
199
|
end
|
200
200
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Clever
|
2
|
-
|
2
|
+
module_extend class_mixin
|
3
3
|
|
4
4
|
class_mixin do
|
5
5
|
def trick?
|
@@ -10,8 +10,8 @@ end
|
|
10
10
|
|
11
11
|
|
12
12
|
module Deft
|
13
|
-
|
14
|
-
|
13
|
+
module_extend self
|
14
|
+
class_extend self
|
15
15
|
|
16
16
|
def technique?
|
17
17
|
true
|
@@ -12,7 +12,7 @@ end
|
|
12
12
|
|
13
13
|
|
14
14
|
module Soopr1
|
15
|
-
|
15
|
+
module_extend SooprMX
|
16
16
|
|
17
17
|
module_mixin do
|
18
18
|
def giv_er
|
@@ -93,7 +93,7 @@ end
|
|
93
93
|
|
94
94
|
module Soopr4
|
95
95
|
include Soopr3
|
96
|
-
|
96
|
+
class_extend DooprCX
|
97
97
|
|
98
98
|
class_mixin do
|
99
99
|
def giv_em
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mixin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hersch Stevenson (xian)
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-09-
|
12
|
+
date: 2008-09-09 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -27,21 +27,21 @@ files:
|
|
27
27
|
- lib/metable/class_methods.rb
|
28
28
|
- lib/mixin.rb
|
29
29
|
- lib/metable.rb
|
30
|
-
- test/
|
31
|
-
- test/test_subjects/meepers.rb
|
30
|
+
- test/mixin_case.rb
|
32
31
|
- test/test_subjects/extenders.rb
|
33
|
-
- test/test_subjects/
|
32
|
+
- test/test_subjects/scopers.rb
|
34
33
|
- test/test_subjects/hopons.rb
|
34
|
+
- test/test_subjects/meepers.rb
|
35
35
|
- test/test_subjects/nudgers.rb
|
36
36
|
- test/test_subjects/includers.rb
|
37
37
|
- test/test_subjects/soopers.rb
|
38
|
+
- test/test_subjects/sleepers.rb
|
38
39
|
- test/test_subjects/clevers.rb
|
39
|
-
- test/mixin_case.rb
|
40
40
|
- README
|
41
41
|
- LICENSE
|
42
42
|
- Rakefile
|
43
43
|
has_rdoc: true
|
44
|
-
homepage: http://
|
44
|
+
homepage: http://api.persapient.com/mixin
|
45
45
|
post_install_message:
|
46
46
|
rdoc_options: []
|
47
47
|
|
@@ -62,7 +62,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
62
62
|
requirements: []
|
63
63
|
|
64
64
|
rubyforge_project: mixin
|
65
|
-
rubygems_version: 1.
|
65
|
+
rubygems_version: 1.0.1
|
66
66
|
signing_key:
|
67
67
|
specification_version: 2
|
68
68
|
summary: An extention to Module that is intended to ease the development of mixins that involve both class and instance methods.
|