local_eval 0.2.2 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -40,10 +40,10 @@ example: capture
40
40
 
41
41
  Since `local_eval` does not alter the `self` inside a block,
42
42
  all methods with an implied receiver will be invoked with respect to
43
- this self. This means that all mutator methods defined on the receiver
43
+ this local self. This means that all mutator methods defined on the receiver
44
44
  will modify state on the block's self rather than on the receiver's
45
45
  self. This is unlikely to be the desired behaviour; and so
46
- using the `capture` method we can redirect the method lookup to
46
+ we can use the `capture` method to redirect method lookup to
47
47
  the actual receiver. All code captured by the `capture` block
48
48
  will be `instance_eval`'d against the actual receiver of the method.
49
49
 
data/Rakefile CHANGED
@@ -19,7 +19,7 @@ def apply_spec_defaults(s)
19
19
  s.description = s.summary
20
20
  s.require_path = 'lib'
21
21
  s.add_dependency("remix",">=0.4.9")
22
- s.add_dependency("object2module",">=0.4.5")
22
+ s.add_dependency("object2module",">=0.5.0")
23
23
  s.homepage = "http://banisterfiend.wordpress.com"
24
24
  s.has_rdoc = 'yard'
25
25
  s.files = Dir["ext/**/extconf.rb", "ext/**/*.h", "ext/**/*.c", "lib/**/*.rb",
@@ -40,7 +40,6 @@ module LocalEval
40
40
  # mix the anonymous module into the block context
41
41
  context.temp_extend functionality, &block
42
42
  end
43
- private :local_eval_with
44
43
 
45
44
  # Performs a `local_eval` on the block with respect to the
46
45
  # receiver.
@@ -1,3 +1,3 @@
1
1
  module LocalEval
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.4"
3
3
  end
@@ -6,6 +6,19 @@ Reset = proc do
6
6
  O = Object.new
7
7
  O2 = Object.new
8
8
  O3 = Object.new
9
+
10
+ class C1
11
+ def c1
12
+ :c1
13
+ end
14
+ end
15
+
16
+ class C2 < C1
17
+ def c2
18
+ :c2
19
+ end
20
+ end
21
+
9
22
  class A
10
23
  def self.a
11
24
  :a
@@ -6,6 +6,7 @@ Reset = proc do
6
6
  O = Object.new
7
7
  O2 = Object.new
8
8
  O3 = Object.new
9
+
9
10
  class A
10
11
  def self.a
11
12
  :a
@@ -36,6 +36,25 @@ describe LocalEval do
36
36
  local_eval(&C.build_proc).should == :love
37
37
  self.singleton_class.remove_method(:love)
38
38
  end
39
+
40
+ it 'should not segfault when inspecting self inside a local_eval' do
41
+ O2.local_eval { self }.should.not == nil
42
+ O2.local_eval { self }.should.not == nil
43
+ end
44
+
45
+ it 'should mix in entire object inheritance chain, including singleton' do
46
+ c = C2.new
47
+ def c.sing
48
+ :sing
49
+ end
50
+
51
+ c.local_eval { c1.should == :c1; c2.should == :c2; sing.should == :sing }
52
+
53
+ lambda { c1 }.should.raise NameError
54
+ lambda { sing }.should.raise NameError
55
+ lambda { c2 }.should.raise NameError
56
+ end
57
+
39
58
  end
40
59
 
41
60
  describe 'local_eval_with' do
@@ -148,6 +167,9 @@ describe LocalEval do
148
167
  instance_variable_get(:@ivar3).should == :ivar3
149
168
  end
150
169
  end
170
+
171
+
172
+
151
173
  end
152
174
 
153
175
  describe 'mixing in a module' do
@@ -36,6 +36,11 @@ describe LocalEval do
36
36
  local_eval(&C.build_proc).should == :love
37
37
  self.singleton_class.remove_method(:love)
38
38
  end
39
+
40
+ it 'should not segfault when inspecting self inside a local_eval' do
41
+ O2.local_eval { self.inspect }
42
+ end
43
+
39
44
  end
40
45
 
41
46
  describe 'local_eval_with' do
@@ -77,9 +82,9 @@ describe LocalEval do
77
82
 
78
83
  it 'should make the method set a local ivar' do
79
84
  instance_variable_defined?(:@v).should == false
80
- lambda { ivar_set }.should.raise NameError
81
- O.local_eval { ivar_set(:@v, 10) }
82
- lambda { ivar_set }.should.raise NameError
85
+ lambda { ivar_set1 }.should.raise NameError
86
+ O.local_eval { ivar_set1(:@v, 10) }
87
+ lambda { ivar_set1 }.should.raise NameError
83
88
  @v.should == 10
84
89
  end
85
90
 
@@ -140,6 +145,17 @@ describe LocalEval do
140
145
  remove_instance_variable(:@ivar3)
141
146
  end
142
147
 
148
+ it 'should work in an instance_eval' do
149
+ o = Object.new
150
+ o.instance_eval do
151
+ O3.local_eval { receiver_ivar_set3 }
152
+ O3.instance_variable_get(:@receiver_ivar3).should == :receiver3
153
+ instance_variable_get(:@ivar3).should == :ivar3
154
+ end
155
+ end
156
+
157
+
158
+
143
159
  end
144
160
 
145
161
  describe 'mixing in a module' do
@@ -16,11 +16,14 @@ end
16
16
  # C.hello
17
17
  # puts @goodbye
18
18
 
19
+ k = C.singleton_class.singleton_class.singleton_class
20
+
19
21
  o = Object.new
20
22
  o.instance_eval {
21
- C.local_eval { hello }
23
+ k.local_eval { puts self; puts self.singleton_class.ancestors }
22
24
  puts @goodbye
23
25
  puts C.instance_variable_get(:@hello)
24
- # puts @hello
25
- puts self.object_id
26
26
  }
27
+
28
+ V = Class.new
29
+ puts V.ancestors
@@ -5,4 +5,4 @@ require 'object2module'
5
5
  o = Object.new
6
6
  o.gen_extend Module.new.singleton_class
7
7
  puts o.singleton_class.ancestors
8
- o.singleton_class.ready_remix
8
+ o.ready_remix
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 2
8
- - 2
9
- version: 0.2.2
8
+ - 4
9
+ version: 0.2.4
10
10
  platform: ruby
11
11
  authors:
12
12
  - John Mair (banisterfiend)
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-11-16 00:00:00 +13:00
17
+ date: 2010-11-17 00:00:00 +13:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -42,9 +42,9 @@ dependencies:
42
42
  - !ruby/object:Gem::Version
43
43
  segments:
44
44
  - 0
45
- - 4
46
45
  - 5
47
- version: 0.4.5
46
+ - 0
47
+ version: 0.5.0
48
48
  type: :runtime
49
49
  version_requirements: *id002
50
50
  description: instance_eval without changing self
@@ -59,18 +59,16 @@ files:
59
59
  - lib/local_eval/version.rb
60
60
  - lib/local_eval/version_flymake.rb
61
61
  - lib/local_eval.rb
62
- - lib/local_eval_flymake.rb
63
62
  - test/helper1.rb
64
63
  - test/helper1_flymake.rb
65
64
  - test/test.rb
66
65
  - test/test_flymake.rb
67
66
  - test/test_segfault.rb
68
67
  - test/test_segfault2.rb
69
- - test/test_segfault_flymake.rb
70
68
  - CHANGELOG
71
69
  - README.markdown
72
70
  - Rakefile
73
- has_rdoc: true
71
+ has_rdoc: yard
74
72
  homepage: http://banisterfiend.wordpress.com
75
73
  licenses: []
76
74
 
@@ -1,133 +0,0 @@
1
- direc = File.dirname(__FILE__)
2
-
3
- require "#{direc}/local_eval/version"
4
- require 'remix'
5
- require 'object2module'
6
-
7
- module LocalEval
8
- module ClassExtensions
9
-
10
- # Find the instance associated with the singleton class
11
- # @return [Object] Instance associated with the singleton class
12
- def __attached__
13
- ObjectSpace.each_object(self).first
14
- end
15
- end
16
-
17
- module ObjectExtensions
18
-
19
- # A more general version of `local_eval`.
20
- # `local_eval_with` allows you to inject arbitrary functionality
21
- # from any number of objects into the block. Methods that use a
22
- # `capture` block are invoked on the object that defines the
23
- # method (and not the local context).
24
- # @param [Array] objs The objects to provide functionality to the block
25
- # @return The value of the block
26
- # @example
27
- # class A; def self.a; puts "a"; end; end
28
- # class B; def self.b; puts "b"; end; end
29
- # class C; def self.c; puts "c"; end; end
30
- # local_eval_with(A, B, C) { a; b; c }
31
- # #=> "a"
32
- # #=> "b"
33
- # #=> "c"
34
- def local_eval_with(*objs, &block)
35
- raise "need a block" if !block_given?
36
-
37
- objs = Array(self) if objs.empty?
38
- context = eval('self', block.binding)
39
-
40
- # if the receiver is the same as the block context then don't
41
- # mix in anything, as functionality is already present.
42
- if objs.include?(context)
43
- objs.delete(context)
44
- return yield if objs.empty?
45
- end
46
-
47
- # add functionality to anonymous module to ease mixing and unmixing
48
- functionality = Module.new.gen_include *objs.map { |o| o.is_a?(Module) ? o.singleton_class : o }
49
-
50
- # mix the anonymous module into the block context
51
- context.temp_extend functionality, &block
52
- end
53
- private :local_eval_with
54
-
55
- # Performs a `local_eval` on the block with respect to the
56
- # receiver.
57
- # `local_eval` has some advantages over `instance_eval` in that it
58
- # does not change `self`. Instead, the functionality in the local
59
- # context is supplemented by the functionality in the
60
- # receiver. Further, if receiver methods utilize a `capture` block
61
- # then the receiver of that `local_eval` becomes the receiver of that
62
- # method call (rather than the local context).
63
- # @return The return value of the block
64
- # @yield The block to `local_eval`
65
- # @example local ivars can be looked up
66
- # class C
67
- # def hello(name)
68
- # "hello #{name}!"
69
- # end
70
- # end
71
- #
72
- # o = C.new
73
- #
74
- # @name = "John"
75
- # o.local_eval { hello(@name) } #=> "hello John!"
76
- def local_eval(&block)
77
- local_eval_with(&block)
78
- end
79
-
80
- # Since `local_eval` does not alter the `self` inside a block,
81
- # all methods with an implied receiver will be invoked with respect to
82
- # this self. This means that all mutator methods defined on the receiver
83
- # will modify state on the block's self rather than on the receiver's
84
- # self. This is unlikely to be the desired behaviour; and so
85
- # using the `capture` method we can redirect the method lookup to
86
- # the actual receiver. All code captured by the `capture` block
87
- # will be `instance_eval`'d against the actual receiver of the
88
- # method.
89
- # @return The return value of the block.
90
- # @yield The block to be evaluated in the receiver's context.
91
- # @example
92
- # class C
93
- # attr_reader :hello
94
- # def self.capture_test
95
- #
96
- # # this code will be run against C
97
- # capture { @hello = :captured }
98
- #
99
- # # this code will be run against the block context
100
- # @goodbye = :goobye
101
- # end
102
- # end
103
- #
104
- # C.local_eval { capture_test }
105
- # C.hello #=> :captured
106
- # @goodbye #=> :goodbye
107
- def capture(&block)
108
-
109
- # 1. Get name of enclosing method (method that invoked
110
- # `capture ` block)
111
- # 2. Find owner of enclosing method (owner is guaranteed to be
112
- # a singleton class)
113
- # 4. Find associated object (attached object) of the singleton class
114
- # 5. This object will be the receiver of the method call, so
115
- # instance_eval on it.
116
- method_name = eval('__method__', block.binding)
117
-
118
- method_owner = method(method_name).owner
119
- attached_object = method_owner.__attached__
120
- attached_object.instance_eval &block
121
- end
122
- alias_method :__capture__, :capture
123
-
124
- end
125
- end
126
-
127
- class Class
128
- include LocalEval::ClassExtensions
129
- end
130
-
131
- class Object
132
- include LocalEval::ObjectExtensions
133
- end
@@ -1,25 +0,0 @@
1
- direc = File.dirname(__FILE__)
2
- require "rubygems"
3
- require "#{direc}/../lib/local_eval"
4
- require 'mult'
5
-
6
- class C
7
- attr_reader :hello
8
- def self.hello
9
- capture { @hello = :captures }
10
- @goodbye = :captured
11
- end
12
- end
13
-
14
- C.local_eval { hello }
15
- @goodbye
16
- C.hello
17
- m = Module.new
18
- m.gen_include Module.new.singleton_class
19
-
20
- o = Object.new
21
- o.instance_eval {
22
- # o.actual_class = C
23
- self.temp_extend(m) { puts self
24
- # C.local_eval { puts self }
25
- }