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 CHANGED
@@ -37,21 +37,15 @@ __WHY?__
37
37
 
38
38
  __EXAMPLES__
39
39
 
40
- Temporarily mix 'Foo' onto the 'self' referenced by _block_:
40
+ Temporarily mix 'SomeModule' onto the 'self' referenced by _block_:
41
41
 
42
- module Foo
43
- def bar() end
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
- block = proc { }
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
@@ -1,3 +1,3 @@
1
1
  class Mixit
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
data/lib/mixit.rb CHANGED
@@ -5,60 +5,78 @@ class Mixit
5
5
 
6
6
  class << self
7
7
  #
8
- # @overload mix(*modules, receiver, &block)
9
- # Temporarily extends the __receiver__ with methods from __modules__.
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 receiver with.
12
+ # A variable number of modules to extend the scope with.
13
13
  #
14
- # @param receiver
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#mix_onto)
20
+ # (see Mixit#mix!)
19
21
  #
20
22
  # @yieldparam object
21
- # (see Mixit#mix_onto)
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
- case args.last
27
- when Proc
28
- scope = args.pop
29
- receiver = scope.binding.eval("self")
30
- modules = args
31
+ options = args.pop
32
+ modules = args
33
+
34
+ if options.has_key?(:scope)
35
+ scope = options[:scope]
31
36
  else
32
- receiver = args.pop
33
- modules = args
37
+ raise ArgumentError, 'missing :scope option.'
34
38
  end
35
-
36
- new(modules).mix_onto(receiver, &block)
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(modules)
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 __receiver__ with methods from {#modules modules}.
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 mix_onto(receiver, &block)
89
+ def mix! &block
72
90
  if block.arity == 1
73
- block.call extend!(receiver, true)
91
+ block.call extend!(true)
74
92
  else
75
93
  begin
76
- ivars = receiver.instance_variables
77
- extend!(receiver, false).instance_eval(&block)
94
+ extend!(false).instance_eval(&block)
78
95
  ensure
79
- (receiver.instance_variables - ivars).each do |ivar|
80
- receiver.send(:remove_instance_variable, ivar)
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 __receiver__ with the methods from {#modules modules}.
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 receiver is extended.
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!(receiver, to_be_cloned=false)
105
- if to_be_cloned
106
- receiver = receiver.clone
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(receiver) { |obj, mod| obj.extend(mod) }
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
- Mixit.mix(@module, block) do
47
- @ok = :no
42
+ @module.instance_eval do
43
+ def cleanup!(scope)
44
+ scope.send(:remove_instance_variable, :@ok)
45
+ end
48
46
  end
49
47
 
50
- instance_variable_defined?(:@ok).must_equal(false)
51
- end
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?(:@set_ivar).must_equal(false)
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
- it 'must remove methods added by mixed-in modules.' do
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.3.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-21 00:00:00.000000000 Z
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: &70339179578900 !ruby/object:Gem::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: *70339179578900
24
+ version_requirements: *70097654179640
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: minitest
27
- requirement: &70339179578400 !ruby/object:Gem::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: *70339179578400
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: 2621427566551580532
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: 2621427566551580532
80
+ hash: -1392924086282936836
81
81
  requirements: []
82
82
  rubyforge_project: mixit
83
83
  rubygems_version: 1.8.11