mixit 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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