如何将方法传递给instance_eval?

时间:2013-04-24 16:37:12

标签: ruby metaprogramming instance-eval

我想在此课程上致电instance_eval

class A
  attr_reader :att
end

传递此方法b

class B
  def b(*args)
    att
  end
end

但这种情况正在发生:

a = A.new
bb = B.new
a.instance_eval(&bb.method(:b)) # NameError: undefined local variable or method `att' for #<B:0x007fb39ad0d568>

b是一个阻止它运行时,b作为一种方法无效。我怎样才能使它发挥作用?

2 个答案:

答案 0 :(得分:0)

目前尚不清楚你的目标是什么。通过在模块中定义类并在每个类中包含模块

,您可以轻松地在类之间共享方法
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

答案 1 :(得分:0)

此答案并未使用所谓的实际方法,但我无需返回Proc或更改A。这是一个DSL,def_b应该有一个有意义的域名,如configure,它更可能在模块或基类中定义。

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

它接受多个定义。它可以只接受这样的单一定义:

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