1

我正在尝试为包含我的模块的任何类创建 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]] = value?

4

1 回答 1

0

因为instance_variable_set在类方法中被调用,所以self被设置为类并被@price设置为类实例变量Stock

但是,您的price方法是实例方法,因此它会尝试@price在实例上查找,但没有找到,并返回默认值。

编辑:这个怎么样:

define_method('price') do 
  @price ||= self.class.instance_variable_get(:@price) || DEFAULT_STOCK_PRICE
end
于 2013-11-03T01:54:58.833 回答