我正在尝试为包含我的模块的任何类创建DSL。它正在处理股票。
这是我的测试:
context 'when price is provided' do
let(:stock_with_price) {
class Stock
include StopLimit
stock_attributes price: 3.33
end
Stock.new
}
it 'sets the price to given value' do
stock_with_price.price.should eq(3.33)
end
end
到目前为止,这是我的模块:
module StopLimit
DEFAULT_STOCK_PRICE = 0
def self.included(base)
attr_accessor :price
def base.stock_attributes(options = {})
define_method('price') do
instance_variable_get("@price") ? instance_variable_get("@price") : DEFAULT_STOCK_PRICE
end
options.each_pair do |attribute, value|
if self.method_defined?(attribute)
instance_variable_set("@#{attribute.to_s}", value)
# raise instance_variable_get("@price").inspect <-- This prints out 3.33!
end
end
end
end
end
我的测试似乎被打破了。 stock.price
正在返回0
。为什么实例变量打印正确的东西,但我的测试失败了?
更新:
这有效:
options.each_pair do |attribute, value|
if self.method_defined?(attribute)
@price = value
end
end
然而,它是硬编码的。如何动态创建和设置实例变量值,以便循环遍历所有属性和值对并为每个创建@ [[attribute]] =值?
答案 0 :(得分:0)
因为在类方法中调用了instance_variable_set
,所以self
被设置为类,@price
被设置为Stock
上的类实例变量。
但是,您的price
方法是实例方法,因此它会尝试在实例上找到@price
,找不到它,并返回默认值。< / p>
编辑: 怎么样:
define_method('price') do
@price ||= self.class.instance_variable_get(:@price) || DEFAULT_STOCK_PRICE
end