【问题标题】:How to set instance variables in a class that includes a module如何在包含模块的类中设置实例变量
【发布时间】:2013-11-03 01:33:40
【问题描述】:

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

【问题讨论】:

    标签: ruby metaprogramming


    【解决方案1】:

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

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

    编辑: 这个怎么样:

    define_method('price') do 
      @price ||= self.class.instance_variable_get(:@price) || DEFAULT_STOCK_PRICE
    end
    

    【讨论】:

    • 那么我该如何真正设置类实例的默认实例变量呢?
    • @Edmund 如果它是类的属性,为什么你希望它成为实例变量?或者反过来说,如果类定义了实例属性,为什么还要在类定义中调用stock_attributes
    • @Edmund 我也许明白。我已经用一个可行的解决方案更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 2015-09-11
    • 1970-01-01
    • 2013-08-22
    • 1970-01-01
    • 2011-10-03
    • 2013-05-17
    • 2012-01-06
    • 1970-01-01
    相关资源
    最近更新 更多