Reputation: 1845
I want to call instance_eval
on this class:
class A
attr_reader :att
end
passing this method b
:
class B
def b(*args)
att
end
end
but this is happening:
a = A.new
bb = B.new
a.instance_eval(&bb.method(:b)) # NameError: undefined local variable or method `att' for #<B:0x007fb39ad0d568>
When b
is a block it works, but b
as a method isn't working. How can I make it work?
Upvotes: 1
Views: 384
Reputation: 1845
This answer does not use a real method as asked, but I didn't need to return a Proc
or change A
. This is a DSL, def_b
should have a meaningful name to the domain, like configure
, and it is more likely to be defined in a module or base class.
class B
class << self
def def_b(&block)
(@b_blocks ||= []) << block
end
def run
return if @b_blocks.nil?
a = A.new
@b_blocks.each { |block| a.instance_eval(&block) }
end
end
def_b do
a
end
end
And it accepts multiple definitions. It could be made accept only a single definition like this:
class B
class << self
def def_b(&block)
raise "b defined twice!" unless @b_block.nil?
@b_block = block
end
def run
A.new.instance_eval(&@b_block) unless @b_block.nil?
end
end
def_b do
a
end
end
Upvotes: 0
Reputation: 20408
It's not clear exactly what you goal is. You can easily share methods between classes by defining them in a module and including the module in each class
module ABCommon
def a
'a'
end
end
class A
include ABCommon
end
Anything = Hash
class B < Anything
include ABCommon
def b(*args)
a
end
def run
puts b
end
end
Upvotes: 0