mixit 0.3.0 → 0.4.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.md +6 -12
- data/lib/mixit/version.rb +1 -1
- data/lib/mixit.rb +82 -45
- data/test/test_mixit.rb +14 -34
- metadata +8 -8
data/README.md
CHANGED
@@ -37,21 +37,15 @@ __WHY?__
|
|
37
37
|
|
38
38
|
__EXAMPLES__
|
39
39
|
|
40
|
-
Temporarily mix '
|
40
|
+
Temporarily mix 'SomeModule' onto the 'self' referenced by _block_:
|
41
41
|
|
42
|
-
|
43
|
-
|
42
|
+
Mixit.temporarily SomeModule, :scope => self do
|
43
|
+
p self.class # => Object
|
44
|
+
p respond_to?(:some_mixed_method) # => true
|
44
45
|
end
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
Mixit.temporarily(Foo, block) do
|
49
|
-
p self.class # => Object
|
50
|
-
p respond_to?(:bar) # => true
|
51
|
-
end
|
52
|
-
|
53
|
-
p self.class # => Object
|
54
|
-
p respond_to?(:bar) # => false
|
47
|
+
p self.class # => Object
|
48
|
+
p respond_to?(:some_mixed_method) # => false
|
55
49
|
|
56
50
|
__INSTALL__
|
57
51
|
|
data/lib/mixit/version.rb
CHANGED
data/lib/mixit.rb
CHANGED
@@ -5,60 +5,78 @@ class Mixit
|
|
5
5
|
|
6
6
|
class << self
|
7
7
|
#
|
8
|
-
# @overload mix(*modules,
|
9
|
-
# Temporarily extends
|
8
|
+
# @overload mix(*modules, options, &block)
|
9
|
+
# Temporarily extends a scope with methods from __modules__.
|
10
10
|
#
|
11
11
|
# @param [Module] modules
|
12
|
-
# A variable number of modules to extend the
|
12
|
+
# A variable number of modules to extend the scope with.
|
13
13
|
#
|
14
|
-
# @param
|
15
|
-
# (see Mixit#mix_onto)
|
14
|
+
# @param [Hash] options
|
16
15
|
#
|
16
|
+
# @option options [Binding, Proc, Object] :scope
|
17
|
+
# The scope to extend.
|
18
|
+
#
|
17
19
|
# @param block
|
18
|
-
# (see Mixit#
|
20
|
+
# (see Mixit#mix!)
|
19
21
|
#
|
20
22
|
# @yieldparam object
|
21
|
-
# (see Mixit#
|
23
|
+
# (see Mixit#mix!)
|
24
|
+
#
|
25
|
+
# @raise [ArgumentError]
|
26
|
+
# If the :scope option is missing.
|
22
27
|
#
|
23
28
|
# @return [void]
|
24
29
|
#
|
25
30
|
def mix(*args, &block)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
+
options = args.pop
|
32
|
+
modules = args
|
33
|
+
|
34
|
+
if options.has_key?(:scope)
|
35
|
+
scope = options[:scope]
|
31
36
|
else
|
32
|
-
|
33
|
-
modules = args
|
37
|
+
raise ArgumentError, 'missing :scope option.'
|
34
38
|
end
|
35
|
-
|
36
|
-
new(modules).
|
39
|
+
|
40
|
+
new(scope, modules).mix!(&block)
|
37
41
|
end
|
38
42
|
alias_method :temporarily, :mix
|
39
43
|
end
|
40
44
|
|
41
|
-
|
42
45
|
#
|
43
46
|
# @return [Array<Module>]
|
44
47
|
# An Array of Module objects.
|
45
48
|
#
|
46
49
|
attr_reader :modules
|
47
|
-
|
50
|
+
|
51
|
+
#
|
52
|
+
# @return [Object]
|
53
|
+
# The scope.
|
54
|
+
#
|
55
|
+
attr_reader :scope
|
56
|
+
|
57
|
+
#
|
58
|
+
# @param [Binding, Proc, Object] scope
|
59
|
+
# A scope to extend.
|
48
60
|
#
|
49
61
|
# @param [Array<Module>] modules
|
50
62
|
# An Array of Module objects.
|
51
63
|
#
|
52
|
-
def initialize
|
64
|
+
def initialize scope, modules
|
53
65
|
@modules = modules
|
54
66
|
@clones = []
|
67
|
+
|
68
|
+
case scope
|
69
|
+
when Binding
|
70
|
+
@scope = scope.eval "self"
|
71
|
+
when Proc
|
72
|
+
@scope = scope.binding.eval "self"
|
73
|
+
else
|
74
|
+
@scope = scope
|
75
|
+
end
|
55
76
|
end
|
56
77
|
|
57
78
|
#
|
58
|
-
# Temporarily extends
|
59
|
-
#
|
60
|
-
# @param [Object] receiver
|
61
|
-
# An object to temporarily extend.
|
79
|
+
# Temporarily extends {#scope} with methods from {#modules modules}.
|
62
80
|
#
|
63
81
|
# @param [Proc] block
|
64
82
|
# A block executed while the object is extended.
|
@@ -68,48 +86,67 @@ class Mixit
|
|
68
86
|
#
|
69
87
|
# @return [void]
|
70
88
|
#
|
71
|
-
def
|
89
|
+
def mix! &block
|
72
90
|
if block.arity == 1
|
73
|
-
block.call extend!(
|
91
|
+
block.call extend!(true)
|
74
92
|
else
|
75
93
|
begin
|
76
|
-
|
77
|
-
extend!(receiver, false).instance_eval(&block)
|
94
|
+
extend!(false).instance_eval(&block)
|
78
95
|
ensure
|
79
|
-
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
@clones.each do |mod|
|
84
|
-
mod.instance_methods(false).each do |meth|
|
85
|
-
mod.send(:remove_method, meth)
|
86
|
-
end
|
87
|
-
end
|
96
|
+
remove_methods!
|
97
|
+
trigger_callback!
|
88
98
|
end
|
89
99
|
end
|
90
100
|
end
|
91
101
|
|
92
102
|
#
|
93
|
-
# Extends
|
94
|
-
#
|
95
|
-
# @param receiver
|
96
|
-
# (see Mixit#mix_onto)
|
103
|
+
# Extends {#scope} with the methods from {#modules modules}.
|
97
104
|
#
|
98
105
|
# @param [Boolean] to_be_cloned
|
99
|
-
# If true, a clone of the
|
106
|
+
# If true, a clone of the scope is extended.
|
100
107
|
#
|
101
108
|
# @return [Object]
|
102
109
|
# Returns the extended object.
|
103
110
|
#
|
104
|
-
def extend!
|
105
|
-
if
|
106
|
-
|
111
|
+
def extend! clone_scope
|
112
|
+
if clone_scope
|
113
|
+
scope = @scope.clone
|
114
|
+
else
|
115
|
+
scope = @scope
|
107
116
|
end
|
108
117
|
|
109
118
|
@clones = @modules.map(&:clone)
|
110
|
-
@clones.inject(
|
119
|
+
@clones.inject(scope) { |obj, mod| obj.extend(mod) }
|
111
120
|
end
|
112
121
|
private :extend!
|
113
122
|
|
123
|
+
#
|
124
|
+
# Remove methods used to extend {#scope} from module(s).
|
125
|
+
#
|
126
|
+
# @return [void]
|
127
|
+
#
|
128
|
+
def remove_methods!
|
129
|
+
@clones.each do |clone|
|
130
|
+
clone.instance_methods(false).each do |meth|
|
131
|
+
clone.send(:remove_method, meth)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
private :remove_methods!
|
136
|
+
|
137
|
+
#
|
138
|
+
# Calls cleanup! on module(s) used to extend a scope.
|
139
|
+
#
|
140
|
+
# @return [void]
|
141
|
+
#
|
142
|
+
def trigger_callback!
|
143
|
+
@clones.each do |clone|
|
144
|
+
if clone.respond_to?(:cleanup!)
|
145
|
+
clone.cleanup!(@scope)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
private :trigger_callback!
|
150
|
+
|
114
151
|
end
|
115
152
|
|
data/test/test_mixit.rb
CHANGED
@@ -6,10 +6,6 @@ context Mixit do
|
|
6
6
|
def callme
|
7
7
|
:ok
|
8
8
|
end
|
9
|
-
|
10
|
-
def set_ivar
|
11
|
-
@set_ivar = 'asdf'
|
12
|
-
end
|
13
9
|
end
|
14
10
|
end
|
15
11
|
|
@@ -17,7 +13,7 @@ context Mixit do
|
|
17
13
|
it 'must provide access to mixed-in methods' do
|
18
14
|
block = proc { }
|
19
15
|
|
20
|
-
Mixit.mix(@module, block) do
|
16
|
+
Mixit.mix(@module, :scope => block) do
|
21
17
|
callme.must_equal(:ok)
|
22
18
|
end
|
23
19
|
end
|
@@ -26,7 +22,7 @@ context Mixit do
|
|
26
22
|
block = proc { }
|
27
23
|
local = :ok
|
28
24
|
|
29
|
-
Mixit.mix(@module, block) do
|
25
|
+
Mixit.mix(@module, :scope => block) do
|
30
26
|
local.must_equal(:ok)
|
31
27
|
end
|
32
28
|
end
|
@@ -35,7 +31,7 @@ context Mixit do
|
|
35
31
|
def callme_() :ok end
|
36
32
|
block = proc { }
|
37
33
|
|
38
|
-
Mixit.mix(@module, block) do
|
34
|
+
Mixit.mix(@module, :scope => block) do
|
39
35
|
callme_.must_equal(:ok)
|
40
36
|
end
|
41
37
|
end
|
@@ -43,39 +39,23 @@ context Mixit do
|
|
43
39
|
it 'must remove instance variables added by the calling block.' do
|
44
40
|
block = proc { }
|
45
41
|
|
46
|
-
|
47
|
-
|
42
|
+
@module.instance_eval do
|
43
|
+
def cleanup!(scope)
|
44
|
+
scope.send(:remove_instance_variable, :@ok)
|
45
|
+
end
|
48
46
|
end
|
49
47
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
it 'must remove instance variables added by mixed-in modules.' do
|
54
|
-
block = proc { }
|
55
|
-
|
56
|
-
Mixit.mix(@module, block) do
|
57
|
-
set_ivar
|
58
|
-
instance_variable_defined?(:@set_ivar).must_equal(true)
|
48
|
+
Mixit.mix(@module, :scope => block) do
|
49
|
+
@ok = :no
|
59
50
|
end
|
60
51
|
|
61
|
-
instance_variable_defined?(:@
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'must not remove pre-existing instance variables.' do
|
65
|
-
block = proc {}
|
66
|
-
@ok = :ok
|
67
|
-
|
68
|
-
Mixit.mix(@module, block) do
|
69
|
-
nil
|
70
|
-
end
|
71
|
-
|
72
|
-
instance_variable_defined?(:@ok).must_equal(true)
|
52
|
+
instance_variable_defined?(:@ok).must_equal(false)
|
73
53
|
end
|
74
54
|
|
75
|
-
|
55
|
+
it 'must remove methods added by mixed-in modules.' do
|
76
56
|
block = proc {}
|
77
57
|
|
78
|
-
Mixit.mix(@module, block) do
|
58
|
+
Mixit.mix(@module, :scope => block) do
|
79
59
|
nil
|
80
60
|
end
|
81
61
|
|
@@ -87,7 +67,7 @@ context Mixit do
|
|
87
67
|
it 'must provide access to mixed-in methods.' do
|
88
68
|
block = proc {}
|
89
69
|
|
90
|
-
Mixit.mix(@module, block) do |receiver|
|
70
|
+
Mixit.mix(@module, :scope => block) do |receiver|
|
91
71
|
receiver.callme.must_equal(:ok)
|
92
72
|
end
|
93
73
|
end
|
@@ -95,7 +75,7 @@ context Mixit do
|
|
95
75
|
it 'must not extend the original receiver with mixed-in methods.' do
|
96
76
|
block = proc {}
|
97
77
|
|
98
|
-
Mixit.mix(@module, block) do |receiver|
|
78
|
+
Mixit.mix(@module, :scope => block) do |receiver|
|
99
79
|
respond_to?(:callme).must_equal(false)
|
100
80
|
end
|
101
81
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mixit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-11-
|
12
|
+
date: 2011-11-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement: &
|
16
|
+
requirement: &70097654179640 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.9.2
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70097654179640
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: minitest
|
27
|
-
requirement: &
|
27
|
+
requirement: &70097654179140 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: '2.5'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70097654179140
|
36
36
|
description: Temporarily extend the calling scope of a block with instance methods
|
37
37
|
from a module.
|
38
38
|
email:
|
@@ -68,7 +68,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
68
68
|
version: '0'
|
69
69
|
segments:
|
70
70
|
- 0
|
71
|
-
hash:
|
71
|
+
hash: -1392924086282936836
|
72
72
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
73
|
none: false
|
74
74
|
requirements:
|
@@ -77,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
77
77
|
version: '0'
|
78
78
|
segments:
|
79
79
|
- 0
|
80
|
-
hash:
|
80
|
+
hash: -1392924086282936836
|
81
81
|
requirements: []
|
82
82
|
rubyforge_project: mixit
|
83
83
|
rubygems_version: 1.8.11
|