I'm trying to make the following work but I'm obviously missing something:
class Person
def fetch
puts 'Fetch it boy!'
end
def action(data)
data.call
end
end
class Animal
def play
Person.new.action(proc { fetch })
end
end
Animal.new.play # undefined local variable or method `fetch' for #<Animal:0x0000000001b172d0>
My goal is to get Person execute a method Animal has chosen. I've also tried using instance_exec but to no avail.
Now I know I can use eval and just pass the method name as a string but I'd like to avoid that.
Any ideas?
Thanks in advance
Disclaimer (of sorts):
Please don't propose code restructuring or rewrites. The purpose of the question is to better understand how blocks behave when passed around between objects.
You are looking for:
object.instance_evalevaluates block, but replacesselfwithin that block (which would normally beselfof the context block was created in) withobject:Note however, that
instance_evalalso passes an object as an argument to the block, which might be problematic if you want to pass a lambda:There is another similar method:
instance_exec. Not only it does not pass self as an argument:but it additionally allows you to pass other arguments:
Naturally, both methods need to be used with extra caution and very sparingly - they are nice when you want to declare class-wide hooks in a declarative manner to be executed on each instance. They should not be used as a mean of interaction between two objects, unless you really know what you are ding and can justify it does not validate encapsulation.