2010-12-08 27 views
1

背景...instance_variable_set(:@屬性,{:brand.to_s =>「蘋果」})將覆蓋所有的屬性,不添加

我正在寫一個解析器,着眼於字符串,並試圖確定什麼他們可能包含的產品。我已經創建了我自己的Token課程來提供幫助。令牌的

class Token < ActiveRecord::BaseWithoutTable 

    attr_accessor :regex 
    attr_accessor :values 

end 

實施例:(其中散列鍵全部對應於數據庫中的列中的產品表)

Token.new(:regex => /apple iphone 4/, :values => { :brand => "Apple", :product => "iPhone", :version => 4}) 

這裏的問題是:在我Parser,當找到Token,我試圖將相關值添加到Product實例,如下所示:

token.values.each do |v| 
    attrib, value = v[0], v[1] 
    my_product.instance_variable_set(:@attributes, { attrib.to_s => value }) 
end 

這個工作除了看起來好像我必須同時設置所有的屬性。如果我分階段執行(即:當我發現新的令牌時),它會用nil覆蓋任何未指定的屬性。我錯過了什麼嗎?有一個更好的方法嗎?

+0

我們能看到你的`Product`模式? – 2010-12-08 04:14:50

+0

爲什麼你使用`instance_variable_set`或者你只是想更新由`token.values`返回的`Hash`中`key`表示的屬性有什麼特別的原因? – Swanand 2010-12-08 08:15:45

回答

0

如果my_productactive_record對象,你可以使用write_attribute而不是instance_variable_set。請注意,這隻會寫屬性即數據庫列:

token.values.each do |v| 
    attrib, value = v[0], v[1] 
    my_product.write_attribute attrib.to_s, value # attrib.to_sym would work too 
end 

而且,如果token.values回報Hash,這是你可以遍歷:

token.values.each do |k, v| 
    my_product.write_attribute k, v 
end 
1

修改現有的值(如果存在的話),而不是覆蓋它:

if attr = my_product.instance_variable_get :@attributes 
    attr[attrib.to_s] = value 
else 
    my_product.instance_variable_get :@attributes, { attrib.to_s => value } 
end 

使用instance_variable_set的粗劣;爲什麼你沒有Product本身的訪問器?

class Product 
    def attributes 
    @attributes ||= {} 
    end 
end 

... 

token.values.each do |attr,v| 
    my_product.attributes.merge!(attr.to_s => v) 
end