规范不是 运行 作为 "sandbox" 创建动态 类

Specs not running as "sandbox" creating dynamic Classes

我有一个带有 define 方法的模块,可以像这样动态创建 class:

require "active_support/all"

class SomeBaseClass
  # code
end

module MyModule
  def self.define(_class_name)
    class_name = _class_name.classify
    Object.const_set(class_name, Class.new(SomeBaseClass))
  end
end

然后,如果我这样做:MyModule.define(:my_class) 我将得到:MyClass

我的规格:

describe "#define" do
  it "creates a dynamic class" do
    MyModule.define("my_class")
    expect(subject.const_defined?("MyClass")).to be_truthy
  end
end

效果很好...但是!当我创建 new spec 定义 MyClass 时,我收到此警告:warning: already initialized constant MyClass

发生这种情况是因为我是在之前的规范中创建的 MyClass。所以,问题是:我怎样才能避免这种情况? 我希望每个规格 "a fresh start"。

更新:基于@giglemad 回答的解决方案...

before do
  Object.send(:remove_const, :MyClass) if Object.const_defined?("MyClass")
end

describe "#define" do
  it "creates a dynamic class" do
    MyModule.define("my_class")
    expect(subject.const_defined?("MyClass")).to be_truthy
  end
end

您可以根据名称 + 一些约定每次定义不同的 class 名称。我使用时间戳来这样做。

def nano_timestamp_string
  Time.now.to_f.to_s.sub('.','')
end

只要您需要一些独特的东西但仍想以相同的方式编写测试,您几乎可以重用该约定。例如,我将它用于独特的电子邮件。如果你仍然想 def 然后 undef 一个同名的常量,那么你可能想使用

Object.send(:remove_const,:Myconst)