规范不是 运行 作为 "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)
我有一个带有 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)