Вот простой код, который для каждого указанного аргумента будет добавлять определенные методы get / set, названные в честь этого аргумента. Если вы напишите attr_option :foo, :bar
, то вы увидите #foo/foo=
и #bar/bar=
методы экземпляра на Config
:
module Configurator
class Config
def initialize()
@options = {}
end
def self.attr_option(*args)
args.each do |a|
if not self.method_defined?(a)
define_method "#{a}" do
@options[:"#{a}"] ||= {}
end
define_method "#{a}=" do |v|
@options[:"#{a}"] = v
end
else
throw Exception.new("already have attr_option for #{a}")
end
end
end
end
end
Пока все хорошо. Я хочу написать несколько тестов RSpec, чтобы убедиться, что этот код действительно выполняет то, что должен. Но есть проблема! Если я вызову attr_option :foo
в одном из тестовых методов, этот метод теперь навсегда определен в Config. Таким образом, последующий тест завершится неудачей, когда он не должен, потому что foo
уже определено:
it "should support a specified option" do
c = Configurator::Config
c.attr_option :foo
# ...
end
it "should support multiple options" do
c = Configurator::Config
c.attr_option :foo, :bar, :baz # Error! :foo already defined
# by a previous test.
# ...
end
Есть ли способ, которым я могу дать каждому тесту анонимный "клон" класса Config
, который не зависит от других?