Module: LocalEval::ObjectExtensions
- Included in:
- Object
- Defined in:
- lib/local_eval.rb
Instance Method Summary collapse
-
#capture { ... } ⇒ Object
(also: #__capture__)
Since ‘local_eval` does not alter the `self` inside a block, all methods with an implied receiver will be invoked with respect to this self.
-
#local_eval { ... } ⇒ Object
Performs a ‘local_eval` on the block with respect to the receiver.
-
#local_eval_with(*objs, &block) ⇒ Object
A more general version of ‘local_eval`.
Instance Method Details
#capture { ... } ⇒ Object Also known as: __capture__
Since ‘local_eval` does not alter the `self` inside a block, all methods with an implied receiver will be invoked with respect to this self. This means that all mutator methods defined on the receiver will modify state on the block’s self rather than on the receiver’s self. This is unlikely to be the desired behaviour; and so using the ‘capture` method we can redirect the method lookup to the actual receiver. All code captured by the `capture` block will be `instance_eval`’d against the actual receiver of the method.
94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/local_eval.rb', line 94 def capture(&block) # 1. Get name of enclosing method (method that invoked # `capture ` block) # 2. Find owner of enclosing method (owner is guaranteed to be # a singleton class) # 4. Find associated object (attached object) of the singleton class # 5. This object will be the receiver of the method call, so # instance_eval on it. method_name = eval('__method__', block.binding) method_owner = method(method_name).owner attached_object = method_owner.__attached__ attached_object.instance_eval &block end |
#local_eval { ... } ⇒ Object
Performs a ‘local_eval` on the block with respect to the receiver. `local_eval` has some advantages over `instance_eval` in that it does not change `self`. Instead, the functionality in the block context is supplemented by the functionality in the receiver.
63 64 65 |
# File 'lib/local_eval.rb', line 63 def local_eval(&block) local_eval_with(&block) end |
#local_eval_with(*objs, &block) ⇒ Object
A more general version of ‘local_eval`. `local_eval_with` allows you to inject arbitrary functionality from any number of objects into the block.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/local_eval.rb', line 24 def local_eval_with(*objs, &block) raise "need a block" if !block_given? objs = Array(self) if objs.empty? context = eval('self', block.binding) # if the receiver is the same as the block context then don't # mix in anything, as functionality is already present. if objs.include?(context) objs.delete(context) return yield if objs.empty? end # add functionality to anonymous module to ease mixing and unmixing functionality = Module.new.gen_include *objs.map { |o| o.is_a?(Module) ? o.singleton_class : o } # mix the anonymous module into the block context context.temp_extend functionality, &block end |