2013-11-03 105 views
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。爲什麼實例變量打印正確的東西,但是我的測試失敗了?

UPDATE:

這工作:

options.each_pair do |attribute, value| 
     if self.method_defined?(attribute) 
      @price = value 
      end 
    end 

然而,這是硬編碼。我將如何動態創建和設置實例變量值,以便我可以遍歷所有屬性和值對,併爲每個值創建@ [[attribute]] =值?

回答

0

由於在類方法中調用instance_variable_set,所以self被設置爲該類,而@price被設置爲Stock上的類實例變量。

然而,你price方法是實例的方法,所以它試圖找到實例@price,沒有找到它,並返回默認值。

編輯: 如何:

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

所以,實際上,我怎麼設置類實例的默認實例變量? – Edmund

+0

@Edmund爲什麼你希望它是一個實例變量,如果它是類的屬性?或者相反,如果它定義了一個實例屬性,爲什麼要在類定義中調用'stock_attributes'? – micahbf

+0

@埃德蒙我也許我明白。我已經用一個工作解決方案更新了我的答案。 – micahbf