在Ruby中定义使用范围外变量的方法

在Ruby中定义使用范围外变量的方法,ruby,metaprogramming,closures,Ruby,Metaprogramming,Closures,我想创建一个Test::unittest\u helper方法,我可以在测试执行后调用它来擦除一堆表。以下是我的总体想法: def self.wipe_models(*models) def teardown models.each do |model| model = model.to_s.camelize.constantize model.connection.execute "delete from #{model.table_name}" e

我想创建一个Test::unittest\u helper方法,我可以在测试执行后调用它来擦除一堆表。以下是我的总体想法:

def self.wipe_models(*models)
  def teardown
    models.each do |model|
      model = model.to_s.camelize.constantize
      model.connection.execute "delete from #{model.table_name}"
    end
  end
end
但是,当运行
teardown
时,我会得到:

未定义的局部变量或方法“模型”

在我看来,“def”块似乎不遵守闭包的常规规则;我无法访问在其范围之外定义的变量


那么,如何访问在“def”方法声明之外定义的变量?

使用类实例变量:

cattr_accessor :models_to_wipe

def self.wipe_models(*models)
  self.models_to_wipe = models
end

def teardown
  self.class.models_to_wipe.each do |model|
    model = model.to_s.camelize.constantize
    model.connection.execute "delete from #{model.table_name}"
  end
end

方法定义在Ruby中不是闭包。
模块
定义
结束
关键字都是范围门。为了在范围门上保持范围,您必须通过一个块;块是闭包,因此在定义它们的范围内运行

def foo
  # since we're in a different scope than the one the block is defined in,
  # setting x here will not affect the result of the yield
  x = 900
  puts yield  #=> outputs "16"
end

# x and the block passed to Proc.new have the same scope
x = 4
square_x = Proc.new { x * x }


foo(&square_x)

您可以使用
define_method
将其作为闭包:

def self.wipe_models(*models)
  define_method(:teardown) do
    models.each do |model|
      model = model.to_s.camelize.constantize
      model.connection.execute "delete from #{model.table_name}"
    end
  end
end

现在,方法主体是一个块,可以访问
模型

…不幸的是,我不能这样做,因为对teardown的调用不在我的控制之下我很害怕,但是谢谢你的确认。