...背景
我正在编写一个解析字符串并尝试确定它们可能包含哪些产品的解析器。我已经创建了自己的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})
(其中散列键都对应于products表中的数据库列。)
问题出在以下问题:在我的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 :(得分: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
答案 1 :(得分:0)
如果my_product
是active_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