remix 0.2.0-i386-mswin32 → 0.2.5-i386-mswin32
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +7 -0
- data/README.markdown +123 -35
- data/Rakefile +3 -3
- data/ext/remix/remix.c +60 -16
- data/lib/1.8/remix.so +0 -0
- data/lib/1.9/remix.so +0 -0
- data/lib/remix.rb +72 -0
- data/lib/remix/c_docs.rb +114 -0
- data/lib/remix/version.rb +1 -1
- data/test/test.rb +137 -0
- metadata +10 -11
data/CHANGELOG
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
27/10/2010 version 0.2.5
|
2
|
+
* added tests
|
3
|
+
* reversed order of arguments for #include_at
|
4
|
+
* made it so first index of #include_at is 1 (not 0, since 0 is host module)
|
5
|
+
* added extend-based methods
|
6
|
+
* reordered modules (Remix::ObjectExtenstions and Remix::ModuleExtensions)
|
7
|
+
* added recursive uninclude
|
1
8
|
26/10/2010 version 0.2.0
|
2
9
|
* added include_at_top, replace_module, module_move_up, etc
|
3
10
|
25/10/2010 version 0.1.0
|
data/README.markdown
CHANGED
@@ -1,54 +1,142 @@
|
|
1
1
|
Remix
|
2
|
-
|
2
|
+
=======
|
3
3
|
|
4
|
-
(
|
5
|
-
MIT license
|
4
|
+
(C) John Mair (banisterfiend) 2010
|
6
5
|
|
7
|
-
|
6
|
+
_Ruby modules remixed and remastered_
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
install the gem: **for testing purposes only**
|
13
|
-
`gem install remix`
|
8
|
+
Remix is a library to give you total control over class and module ancestor
|
9
|
+
chains.
|
14
10
|
|
15
|
-
|
11
|
+
Using Remix you can add a module at any point in the chain,
|
12
|
+
remove modules, replace modules, move modules around and otherwise
|
13
|
+
'remix' your modules.
|
16
14
|
|
17
|
-
*
|
18
|
-
*
|
19
|
-
*
|
20
|
-
* include_after(AfterMod, Mod)
|
21
|
-
* swap_modules(Mod1, Mod2)
|
22
|
-
* remove_module(Mod)
|
23
|
-
* module_move_up(Mod)
|
24
|
-
* module_move_down(Mod)
|
25
|
-
* replace_module(Mod1, Mod2)
|
26
|
-
* ...more to come!
|
15
|
+
* Install the [gem](https://rubygems.org/gems/remix): `gem install remix`
|
16
|
+
* Read the [documentation](http://rdoc.info/github/banister/remix/master/file/README.markdown)
|
17
|
+
* See the [source code](http://github.com/banister/remix)
|
27
18
|
|
28
|
-
example:
|
19
|
+
example: include_at_top():
|
20
|
+
--------------------------
|
29
21
|
|
30
|
-
|
22
|
+
Using `include_at_top` we can include a module at the top of a chain
|
23
|
+
rather than at the bottom (the default).
|
24
|
+
|
25
|
+
# ... modules A, B, C, and J defined above...
|
26
|
+
|
27
|
+
module M
|
28
|
+
include A, B, C
|
29
|
+
end
|
30
|
+
|
31
|
+
M.ancestors #=> [M, A, B, C]
|
32
|
+
|
33
|
+
# Now let's insert a module between A and B
|
34
|
+
M.include_at_top J
|
35
|
+
|
36
|
+
# Modified ancestor chain
|
37
|
+
M.ancestors #=> [M, A, B, C, J]
|
38
|
+
|
39
|
+
example: unextend()
|
40
|
+
--------------------
|
41
|
+
|
42
|
+
Like the Mixico library Remix allows you to unextend
|
43
|
+
(or uninclude) modules from inheritance chains; but also extends this
|
44
|
+
functionality by (optionally) removing nested modules too:
|
45
|
+
|
46
|
+
|
47
|
+
# ...modules A, B defined above...
|
48
|
+
|
49
|
+
module C
|
50
|
+
include A, B
|
51
|
+
end
|
52
|
+
|
53
|
+
D = Object.new
|
54
|
+
D.extend C
|
55
|
+
D.singleton_class.ancestors #=> [C, A, B, Object, ...]
|
56
|
+
|
57
|
+
# remove entire nested module C by passing true as second parameter
|
58
|
+
D.unextend C, true
|
59
|
+
|
60
|
+
D.singleton_class.ancestors #=> [Object, ...]
|
61
|
+
|
62
|
+
Special features
|
63
|
+
------------------
|
31
64
|
|
32
|
-
|
65
|
+
Remix is intelligent enough to manipulate classes as well as
|
66
|
+
modules:
|
33
67
|
|
34
|
-
class
|
35
|
-
|
68
|
+
class D < C
|
69
|
+
include M
|
36
70
|
end
|
71
|
+
|
72
|
+
D.ancestors #=> [D, M, C]
|
73
|
+
|
74
|
+
D.swap_modules C, M
|
75
|
+
|
76
|
+
D.ancestors #=> [D, C, M]
|
77
|
+
|
78
|
+
It does this by first converting all superclasses to Included Modules
|
79
|
+
before remixing takes place.
|
37
80
|
|
38
|
-
|
81
|
+
How it works
|
82
|
+
--------------
|
39
83
|
|
40
|
-
|
84
|
+
Remix is a C-based extension that directly manipulates the superclass
|
85
|
+
pointers of Included Modules.
|
41
86
|
|
42
|
-
|
87
|
+
Companion Libraries
|
88
|
+
--------------------
|
43
89
|
|
44
|
-
|
90
|
+
Remix is one of a series of experimental libraries that mess with
|
91
|
+
the internals of Ruby to bring new and interesting functionality to
|
92
|
+
the language, see also:
|
45
93
|
|
46
|
-
|
94
|
+
* [Real Include](http://github.com/banister/real_include) - Brings in
|
95
|
+
module singleton classes during an include. No more ugly ClassMethods and included() hook hacks.
|
96
|
+
* [Object2module](http://github.com/banister/object2module) - Convert Classes and Objects to Modules so they can be extended/included
|
97
|
+
* [Prepend](http://github.com/banister/prepend) - Prepends modules in front of a class; so method lookup starts with the module
|
98
|
+
* [GenEval](http://github.com/banister/gen_eval) - A strange new breed of instance_eval
|
47
99
|
|
48
|
-
|
100
|
+
Full list of functions
|
101
|
+
----------------------
|
49
102
|
|
50
|
-
|
103
|
+
**include-based functions:**
|
51
104
|
|
52
|
-
|
53
|
-
|
54
|
-
|
105
|
+
* include_at(index)
|
106
|
+
* include_at_top(mod)
|
107
|
+
* include_before(before_mod, mod)
|
108
|
+
* include_after(after_mod, mod)
|
109
|
+
* swap_modules(mod1, mod2)
|
110
|
+
* uninclude(mod, recurse=fale)
|
111
|
+
* module_move_up(mod)
|
112
|
+
* module_move_down(mod)
|
113
|
+
* replace_module(mod1, mod2)
|
114
|
+
|
115
|
+
**extend-based functions:**
|
116
|
+
|
117
|
+
* extend_at(index)
|
118
|
+
* extend_at_top(mod)
|
119
|
+
* extend_before(before_mod, mod)
|
120
|
+
* extend_after(after_mod, mod)
|
121
|
+
* swap_extended_modules(mod1, mod2)
|
122
|
+
* replace_module(mod1, mod2)
|
123
|
+
* unextend(mod, recurse=false)
|
124
|
+
* extended_module_move_up(mod)
|
125
|
+
* extended_module_move_down(mod)
|
126
|
+
|
127
|
+
Limitations
|
128
|
+
------------
|
129
|
+
|
130
|
+
Remix does not currently reorder the singleton classes of superclasses
|
131
|
+
to reflect the new position of the class. This functionality is coming
|
132
|
+
soon.
|
133
|
+
|
134
|
+
Contact
|
135
|
+
-------
|
136
|
+
|
137
|
+
Problems or questions contact me at [github](http://github.com/banister)
|
138
|
+
|
139
|
+
Dedication
|
140
|
+
----------
|
141
|
+
|
142
|
+
For Rue (1977-)
|
data/Rakefile
CHANGED
@@ -25,10 +25,10 @@ specification = Gem::Specification.new do |s|
|
|
25
25
|
s.has_rdoc = 'yard'
|
26
26
|
|
27
27
|
#s.extensions = ["ext/remix/extconf.rb"]
|
28
|
-
s.files =
|
29
|
-
"lib/remix.rb", "lib/remix/version.rb"] +
|
28
|
+
s.files =
|
30
29
|
["lib/1.9/remix.so", "lib/1.8/remix.so"] +
|
31
|
-
|
30
|
+
FileList["ext/**/extconf.rb", "ext/**/*.h", "ext/**/*.c", "lib/**/*.rb", "test/*.rb",
|
31
|
+
"CHANGELOG", "README.markdown", "Rakefile"].to_a
|
32
32
|
end
|
33
33
|
|
34
34
|
Rake::GemPackageTask.new(specification) do |package|
|
data/ext/remix/remix.c
CHANGED
@@ -106,6 +106,9 @@ get_source_module(VALUE mod)
|
|
106
106
|
static VALUE
|
107
107
|
retrieve_before_mod(VALUE m, VALUE before)
|
108
108
|
{
|
109
|
+
if (!RTEST(rb_obj_is_kind_of(before, rb_cModule)) && TYPE(before) != T_FALSE)
|
110
|
+
rb_raise(rb_eTypeError, "Must be a Module or Class type.");
|
111
|
+
|
109
112
|
VALUE k = get_source_module(RCLASS_SUPER(m));
|
110
113
|
while(k != before && m != 0 && m != rb_cObject) {
|
111
114
|
m = RCLASS_SUPER(m);
|
@@ -120,6 +123,9 @@ retrieve_before_mod(VALUE m, VALUE before)
|
|
120
123
|
static VALUE
|
121
124
|
retrieve_mod(VALUE m, VALUE after)
|
122
125
|
{
|
126
|
+
if (!RTEST(rb_obj_is_kind_of(after, rb_cModule)) && TYPE(after) != T_FALSE)
|
127
|
+
rb_raise(rb_eTypeError, "Must be a Module or Class type.");
|
128
|
+
|
123
129
|
VALUE k = get_source_module(m);
|
124
130
|
while(k != after && m != 0 && m != rb_cObject) {
|
125
131
|
m = RCLASS_SUPER(m);
|
@@ -191,19 +197,25 @@ VALUE
|
|
191
197
|
rb_include_before(VALUE self, VALUE before, VALUE mod)
|
192
198
|
{
|
193
199
|
rb_prepare_for_remix(self);
|
200
|
+
|
201
|
+
if (before == self)
|
202
|
+
rb_raise(rb_eRuntimeError, "Prepend not supported yet!");
|
203
|
+
|
194
204
|
rb_include_module(retrieve_before_mod(self, before), mod);
|
195
205
|
return self;
|
196
206
|
}
|
197
207
|
|
198
208
|
VALUE
|
199
|
-
rb_include_at(VALUE self, VALUE
|
209
|
+
rb_include_at(VALUE self, VALUE rb_index, VALUE mod)
|
200
210
|
{
|
201
211
|
rb_prepare_for_remix(self);
|
212
|
+
|
213
|
+
Check_Type(rb_index, T_FIXNUM);
|
202
214
|
|
203
215
|
int index = FIX2INT(rb_index);
|
204
216
|
VALUE m = self;
|
205
217
|
|
206
|
-
int i =
|
218
|
+
int i = 1;
|
207
219
|
while(i++ < index && RCLASS_SUPER(m) != 0 && RCLASS_SUPER(m) != rb_cObject)
|
208
220
|
m = RCLASS_SUPER(m);
|
209
221
|
|
@@ -236,16 +248,40 @@ rb_swap_modules(VALUE self, VALUE mod1, VALUE mod2)
|
|
236
248
|
return self;
|
237
249
|
}
|
238
250
|
|
251
|
+
static void
|
252
|
+
remove_nested_module(VALUE included_mod, VALUE module)
|
253
|
+
{
|
254
|
+
VALUE source_mod = get_source_module(RCLASS_SUPER(included_mod));
|
255
|
+
|
256
|
+
if (source_mod == rb_cObject || source_mod == Qfalse)
|
257
|
+
return;
|
258
|
+
else if (source_mod == get_source_module(RCLASS_SUPER(module))) {
|
259
|
+
remove_nested_module(RCLASS_SUPER(included_mod), RCLASS_SUPER(module));
|
260
|
+
RCLASS_SUPER(included_mod) = RCLASS_SUPER(RCLASS_SUPER(included_mod));
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
239
264
|
VALUE
|
240
|
-
|
265
|
+
rb_uninclude(int argc, VALUE * argv, VALUE self)
|
241
266
|
{
|
242
267
|
rb_prepare_for_remix(self);
|
243
268
|
|
269
|
+
VALUE mod1, recurse = Qfalse;
|
270
|
+
rb_scan_args(argc, argv, "11", &mod1, &recurse);
|
271
|
+
|
272
|
+
if (!RTEST(rb_mod_include_p(self, mod1)))
|
273
|
+
rb_raise(rb_eArgError, "Module not found");
|
274
|
+
|
244
275
|
VALUE before = retrieve_before_mod(self, mod1);
|
245
276
|
VALUE included_mod = retrieve_mod(self, mod1);
|
246
277
|
|
247
278
|
if (mod1 == rb_cObject) rb_raise(rb_eRuntimeError, "can't delete Object");
|
279
|
+
|
280
|
+
if (RTEST(recurse))
|
281
|
+
remove_nested_module(included_mod, mod1);
|
282
|
+
|
248
283
|
RCLASS_SUPER(before) = RCLASS_SUPER(included_mod);
|
284
|
+
|
249
285
|
rb_clear_cache();
|
250
286
|
|
251
287
|
return self;
|
@@ -260,7 +296,7 @@ rb_replace_module(VALUE self, VALUE mod1, VALUE mod2)
|
|
260
296
|
return rb_swap_modules(self, mod1, mod2);
|
261
297
|
|
262
298
|
VALUE before = retrieve_before_mod(self, mod1);
|
263
|
-
|
299
|
+
rb_uninclude(1, &mod1, self);
|
264
300
|
rb_include_module(before, mod2);
|
265
301
|
return self;
|
266
302
|
}
|
@@ -268,17 +304,25 @@ rb_replace_module(VALUE self, VALUE mod1, VALUE mod2)
|
|
268
304
|
void
|
269
305
|
Init_remix()
|
270
306
|
{
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
rb_define_method(
|
276
|
-
rb_define_method(
|
277
|
-
|
278
|
-
rb_define_method(
|
279
|
-
|
280
|
-
|
281
|
-
rb_define_method(
|
282
|
-
|
307
|
+
VALUE mRemix = rb_define_module("Remix");
|
308
|
+
VALUE mModuleExtensions = rb_define_module_under(mRemix, "ModuleExtensions");
|
309
|
+
|
310
|
+
rb_define_method(mModuleExtensions, "ready_remix", rb_prepare_for_remix, 0);
|
311
|
+
rb_define_method(mModuleExtensions, "module_move_up", rb_module_move_up, 1);
|
312
|
+
rb_define_method(mModuleExtensions, "module_move_down", rb_module_move_down, 1);
|
313
|
+
|
314
|
+
rb_define_method(mModuleExtensions, "include_at", rb_include_at, 2);
|
315
|
+
rb_define_method(mModuleExtensions, "include_below", rb_include_before, 2);
|
316
|
+
rb_define_alias(mModuleExtensions, "include_before", "include_below");
|
317
|
+
rb_define_method(mModuleExtensions, "include_above", rb_include_after, 2);
|
318
|
+
rb_define_alias(mModuleExtensions, "include_after", "include_above");
|
319
|
+
rb_define_method(mModuleExtensions, "include_at_top", rb_include_at_top, 1);
|
320
|
+
|
321
|
+
rb_define_method(mModuleExtensions, "swap_modules", rb_swap_modules, 2);
|
322
|
+
rb_define_method(mModuleExtensions, "uninclude", rb_uninclude, -1);
|
323
|
+
rb_define_alias(mModuleExtensions, "remove_module", "uninclude");
|
324
|
+
rb_define_method(mModuleExtensions, "replace_module", rb_replace_module, 2);
|
325
|
+
|
326
|
+
rb_include_module(rb_cModule, mModuleExtensions);
|
283
327
|
}
|
284
328
|
|
data/lib/1.8/remix.so
CHANGED
Binary file
|
data/lib/1.9/remix.so
CHANGED
Binary file
|
data/lib/remix.rb
CHANGED
@@ -2,6 +2,7 @@ direc = File.dirname(__FILE__)
|
|
2
2
|
|
3
3
|
require 'rbconfig'
|
4
4
|
require "#{direc}/remix/version"
|
5
|
+
require "#{direc}/remix/c_docs"
|
5
6
|
|
6
7
|
dlext = Config::CONFIG['DLEXT']
|
7
8
|
|
@@ -15,3 +16,74 @@ rescue LoadError => e
|
|
15
16
|
require "#{direc}/remix.#{dlext}"
|
16
17
|
end
|
17
18
|
|
19
|
+
module Kernel
|
20
|
+
# :nodoc:
|
21
|
+
def singleton_class
|
22
|
+
class << self; self; end
|
23
|
+
end if !respond_to?(:singleton_class)
|
24
|
+
end
|
25
|
+
|
26
|
+
module Remix::ObjectExtensions
|
27
|
+
|
28
|
+
# Like `include_at()` but for the singleton class
|
29
|
+
# @see Module#include_at
|
30
|
+
def extend_at(index, mod)
|
31
|
+
singleton_class.include_at(index, mod)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Like `include_below()` but for the singleton class
|
35
|
+
# @see Module#include_below
|
36
|
+
def extend_below(mod1, mod2)
|
37
|
+
singleton_class.include_below(mod1, mod2)
|
38
|
+
end
|
39
|
+
alias_method :extend_before, :extend_below
|
40
|
+
|
41
|
+
# Like `include_above()` but for the singleton class
|
42
|
+
# @see Module#include_above
|
43
|
+
def extend_above(mod1, mod2)
|
44
|
+
singleton_class.include_above(mod1, mod2)
|
45
|
+
end
|
46
|
+
alias_method :extend_after, :extend_above
|
47
|
+
|
48
|
+
# Like `uninclude()` but for the singleton class
|
49
|
+
# @see Module#uninclude
|
50
|
+
def unextend(mod, recurse = false)
|
51
|
+
singleton_class.uninclude(mod, recurse)
|
52
|
+
end
|
53
|
+
alias_method :remove_extended_module, :unextend
|
54
|
+
|
55
|
+
# Like `include_at_top()` but for the singleton class
|
56
|
+
# @see Module#include_at_top
|
57
|
+
def extend_at_top(mod)
|
58
|
+
singleton_class.include_at_top(mod)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Like `swap_modules()` but for the singleton class
|
62
|
+
# @see Module#swap_modules
|
63
|
+
def swap_extended_modules(mod1, mod2)
|
64
|
+
singleton_class.swap_modules(mod1, mod2)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Like `module_move_up()` but for the singleton class
|
68
|
+
# @see Module#module_move_up
|
69
|
+
def extended_module_move_up(mod)
|
70
|
+
singleton_class.module_move_up(mod)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Like `module_move_down()` but for the singleton class
|
74
|
+
# @see Module#module_move_down
|
75
|
+
def extended_module_move_down(mod)
|
76
|
+
singleton_class.module_move_down(mod)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Like `replace_module()` but for the singleton class
|
80
|
+
# @see Module#replace_module_down
|
81
|
+
def replace_extended_module(mod1, mod2)
|
82
|
+
singleton_class.replace_module(mod1, mod2)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
class Object
|
88
|
+
include Remix::ObjectExtensions
|
89
|
+
end
|
data/lib/remix/c_docs.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
module Remix
|
2
|
+
module ModuleExtensions
|
3
|
+
# Includes a module at a particular index in the ancestor
|
4
|
+
# chain.
|
5
|
+
#
|
6
|
+
# @param [Fixnum] index The index where the module will be included
|
7
|
+
# (must be > 1.)
|
8
|
+
# @param [Module] mod The module to include
|
9
|
+
# @return [Module] The receiver
|
10
|
+
# @example
|
11
|
+
# module M end
|
12
|
+
# module N end
|
13
|
+
# module O end
|
14
|
+
# module P
|
15
|
+
# include M, N
|
16
|
+
# end
|
17
|
+
# P.include_at 2, O
|
18
|
+
# P.ancestors #=> [P, M, O, N]
|
19
|
+
def include_at(index, mod) end
|
20
|
+
|
21
|
+
# Includes a module below a specific module in the ancestor chain.
|
22
|
+
# @param [Module] mod1 Module with position
|
23
|
+
# @param [Module] mod2 Module that will be included
|
24
|
+
# @return [Module] The receiver
|
25
|
+
# @example
|
26
|
+
# M.ancestors #=> [M, A, B]
|
27
|
+
# M.include_below B, J
|
28
|
+
# M.ancestors #=> [M, A, J, B]
|
29
|
+
def include_below(mod1, mod2) end
|
30
|
+
|
31
|
+
# Includes a module above a specific module in the ancestor chain.
|
32
|
+
# @param [Module] mod1 Module with position
|
33
|
+
# @param [Module] mod2 Module that will be included
|
34
|
+
# @return [Module] The receiver
|
35
|
+
# @example
|
36
|
+
# M.ancestors #=> [M, A, B]
|
37
|
+
# M.include_above B, J
|
38
|
+
# M.ancestors #=> [M, A, B, J]
|
39
|
+
def include_above(mod1, mod) end
|
40
|
+
|
41
|
+
# Includes a module at top of ancestor chain
|
42
|
+
# @param [Module] mod Module that will be included
|
43
|
+
# @return [Module] The receiver
|
44
|
+
# @example
|
45
|
+
# M.ancestors #=> [M, A, B]
|
46
|
+
# M.include_at_top J
|
47
|
+
# M.ancestors #=> [M, A, B, J]
|
48
|
+
def include_at_top(mod) end
|
49
|
+
|
50
|
+
# Moves a module up one position in the ancestor chain.
|
51
|
+
# Module must already be in ancestor chain.
|
52
|
+
# @param [Module] Module to move up
|
53
|
+
# @return [Module] The receiver
|
54
|
+
# @example
|
55
|
+
# M.ancestors #=> [M, A, B]
|
56
|
+
# M.module_move_up A
|
57
|
+
# M.ancestors #=> [M, B, A]
|
58
|
+
def module_move_up(mod) end
|
59
|
+
|
60
|
+
# Moves a module down one position in the ancestor chain.
|
61
|
+
# Module must already be in ancestor chain.
|
62
|
+
# @param [Module] Module to move down
|
63
|
+
# @return [Module] The receiver
|
64
|
+
# @example
|
65
|
+
# M.ancestors #=> [M, A, B]
|
66
|
+
# M.module_move_down B
|
67
|
+
# M.ancestors #=> [M, B, A]
|
68
|
+
def module_move_down(mod) end
|
69
|
+
|
70
|
+
# Unincludes a module from an ancestor chain with optional recursion
|
71
|
+
# for nested modules.
|
72
|
+
# @param [Module] mod The module to uninclude
|
73
|
+
# @param [Boolean] recurse Set to true to remove nested modules
|
74
|
+
# @return [Module] The receiver
|
75
|
+
# @example
|
76
|
+
# module C
|
77
|
+
# include A, B
|
78
|
+
# end
|
79
|
+
# M.ancestors #=> [M, C, A, B]
|
80
|
+
# M.uninclude C
|
81
|
+
# M.ancestors #=> [M, A, B]
|
82
|
+
# @example With recursion
|
83
|
+
# module C
|
84
|
+
# include A, B
|
85
|
+
# end
|
86
|
+
# M.ancestors #=> [M, C, A, B]
|
87
|
+
# M.uninclude C, true
|
88
|
+
# M.ancestors #=> [M]
|
89
|
+
def uninclude(mod, recurse = false) end
|
90
|
+
|
91
|
+
# Swaps the position of two modules that already exist in an
|
92
|
+
# ancestor chain.
|
93
|
+
# @param [Module] mod1 Module to swap
|
94
|
+
# @param [Module] mod2 Module to swap
|
95
|
+
# @return [Module] The receiver
|
96
|
+
# @example
|
97
|
+
# M.ancestors #=> [M, A, B, C, D]
|
98
|
+
# M.swap_modules A, D
|
99
|
+
# M.ancestors #=> [M, D, B, C, A]
|
100
|
+
def swap_modules(mod1, mod2) end
|
101
|
+
|
102
|
+
# Replaces a module with another module that is not already in the
|
103
|
+
# ancestor chain.
|
104
|
+
# @param [Module] mod1 The module to be replaced
|
105
|
+
# @param [Module] mod2 The module that will replace
|
106
|
+
# @return [Module] The receiver
|
107
|
+
# @example
|
108
|
+
# J = Module.new
|
109
|
+
# M.ancestors #=> [M, A, B]
|
110
|
+
# M.replace_module B, J
|
111
|
+
# M.ancestors #=> [M, A, J]
|
112
|
+
def replace_module(mod1, mod2) end
|
113
|
+
end
|
114
|
+
end
|
data/lib/remix/version.rb
CHANGED
data/test/test.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require '../lib/remix'
|
3
|
+
require 'bacon'
|
4
|
+
|
5
|
+
class Module
|
6
|
+
public :include, :remove_const
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'Test basic remix functionality' do
|
10
|
+
before do
|
11
|
+
A = Module.new
|
12
|
+
B = Module.new
|
13
|
+
C = Module.new
|
14
|
+
J = Module.new
|
15
|
+
|
16
|
+
M = Module.new
|
17
|
+
|
18
|
+
M.include A, B
|
19
|
+
M.extend A, B
|
20
|
+
end
|
21
|
+
|
22
|
+
after do
|
23
|
+
Object.remove_const(:A)
|
24
|
+
Object.remove_const(:B)
|
25
|
+
Object.remove_const(:C)
|
26
|
+
Object.remove_const(:M)
|
27
|
+
Object.remove_const(:J)
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'extend-based methods' do
|
31
|
+
describe 'extend_after' do
|
32
|
+
it 'should insert module into correct position in singleton class' do
|
33
|
+
M.extend_above B, J
|
34
|
+
M.singleton_class.ancestors
|
35
|
+
M.singleton_class.ancestors[0..2].should == [A, B, J]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'unextend' do
|
40
|
+
it 'should unextend the module' do
|
41
|
+
C.include A, B
|
42
|
+
M.extend C
|
43
|
+
M.singleton_class.ancestors[0..2].should == [C, A, B]
|
44
|
+
M.unextend C
|
45
|
+
M.singleton_class.ancestors[0..1].should == [A, B]
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should unextend the nested module' do
|
49
|
+
C.include A, B
|
50
|
+
M.extend C
|
51
|
+
M.extend J
|
52
|
+
M.singleton_class.ancestors[0..3].should == [J, C, A, B]
|
53
|
+
M.unextend C, true
|
54
|
+
M.singleton_class.ancestors[0..1].should == [J, Module]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'include-based methods' do
|
60
|
+
describe 'include_after' do
|
61
|
+
it 'should insert module into correct position' do
|
62
|
+
M.include_after A, C
|
63
|
+
M.ancestors[2].should == C
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe 'include_before' do
|
68
|
+
it 'should insert module into correct position' do
|
69
|
+
M.include_before B, C
|
70
|
+
M.ancestors[2].should == C
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe 'include_at_top' do
|
75
|
+
it 'should insert module at top of chain' do
|
76
|
+
M.include_at_top C
|
77
|
+
M.ancestors.last.should == C
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe 'swap_modules' do
|
82
|
+
it 'should interchange modules' do
|
83
|
+
M.ancestors[1..2].should == [A, B]
|
84
|
+
M.swap_modules A, B
|
85
|
+
M.ancestors[1..2].should == [B, A]
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'module_move_up' do
|
90
|
+
it 'should move module up the chain' do
|
91
|
+
M.ancestors[1..2].should == [A, B]
|
92
|
+
M.module_move_up A
|
93
|
+
M.ancestors[1..2].should == [B, A]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe 'module_move_down' do
|
98
|
+
it 'should move module down the chain' do
|
99
|
+
M.ancestors[1..2].should == [A, B]
|
100
|
+
M.module_move_down B
|
101
|
+
M.ancestors[1..2].should == [B, A]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe 'include_at' do
|
106
|
+
it 'should include module at specified index' do
|
107
|
+
M.include_at(1, C)
|
108
|
+
M.ancestors[1].should == C
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe 'remove_module' do
|
113
|
+
it 'should remove the module' do
|
114
|
+
M.ancestors[1..2].should == [A, B]
|
115
|
+
M.remove_module A
|
116
|
+
M.ancestors[1..2].should == [B]
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should remove recursively if second parameter is true' do
|
120
|
+
klass = Module.new
|
121
|
+
klass.include J, M, C
|
122
|
+
klass.ancestors[1..-1].should == [J, M, A, B, C]
|
123
|
+
klass.remove_module M, true
|
124
|
+
klass.ancestors[1..-1].should == [J, C]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe 'replace_module' do
|
129
|
+
it 'should replace the module with another' do
|
130
|
+
M.ancestors[1..2].should == [A, B]
|
131
|
+
M.replace_module B, C
|
132
|
+
M.ancestors[1..2].should == [A, C]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: remix
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 23
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 0
|
8
7
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
8
|
+
- 5
|
9
|
+
version: 0.2.5
|
11
10
|
platform: i386-mswin32
|
12
11
|
authors:
|
13
12
|
- John Mair (banisterfiend)
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2010-10-
|
17
|
+
date: 2010-10-27 00:00:00 +13:00
|
19
18
|
default_executable:
|
20
19
|
dependencies: []
|
21
20
|
|
@@ -28,16 +27,18 @@ extensions: []
|
|
28
27
|
extra_rdoc_files: []
|
29
28
|
|
30
29
|
files:
|
31
|
-
- Rakefile
|
32
|
-
- README.markdown
|
33
|
-
- CHANGELOG
|
34
|
-
- lib/remix.rb
|
35
|
-
- lib/remix/version.rb
|
36
30
|
- lib/1.9/remix.so
|
37
31
|
- lib/1.8/remix.so
|
38
32
|
- ext/remix/extconf.rb
|
39
33
|
- ext/remix/compat.h
|
40
34
|
- ext/remix/remix.c
|
35
|
+
- lib/remix/c_docs.rb
|
36
|
+
- lib/remix/version.rb
|
37
|
+
- lib/remix.rb
|
38
|
+
- test/test.rb
|
39
|
+
- CHANGELOG
|
40
|
+
- README.markdown
|
41
|
+
- Rakefile
|
41
42
|
has_rdoc: yard
|
42
43
|
homepage: http://banisterfiend.wordpress.com
|
43
44
|
licenses: []
|
@@ -52,7 +53,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
52
53
|
requirements:
|
53
54
|
- - ">="
|
54
55
|
- !ruby/object:Gem::Version
|
55
|
-
hash: 3
|
56
56
|
segments:
|
57
57
|
- 0
|
58
58
|
version: "0"
|
@@ -61,7 +61,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
61
61
|
requirements:
|
62
62
|
- - ">="
|
63
63
|
- !ruby/object:Gem::Version
|
64
|
-
hash: 3
|
65
64
|
segments:
|
66
65
|
- 0
|
67
66
|
version: "0"
|