Module: LocalEval::ObjectExtensions
- Included in:
- Object
- Defined in:
- lib/local_eval.rb
Instance Method Summary collapse
-
#capture { ... } ⇒ Object
(also: #__capture__)
Since
local_evaldoes not alter theselfinside a block, all methods with an implied receiver will be invoked with respect to this self. -
#local_eval { ... } ⇒ Object
Performs a
local_evalon 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 |