我正在通过哈希进行一些递归来构建attr_accessor和类实例。 我从主哈希中获取所有值。 我用它来描述一个事件(舞蹈课和俱乐部),我希望能够存储这样的信息:
data = {:datetime => '2011-11-23', :duration => '90', :lesson => {:price => '£7', :level => 'all'}, :club => {:price => "4"}
这样我就可以轻松检索lesson[:price]
和club[:price]
。
使用我所具有的递归,我检查主散列的每个项目以查看该值是否为散列。如果是,我重新启动递归并填充所有值。
问题是我不能让2个与lesson[:price]
同名的变量与club[:price]
发生碰撞。
这是递归:
class Event
#attr_reader :datetime, :duration, :class, :price, :level
def init(data, recursion)
data.each do |name, value|
if value.is_a? Hash
init(value, recursion+1)
else
instance_variable_set("@#{name}", value)
self.class.send(:attr_accessor, name)
end
end
end
它跳过课程和俱乐部级别,并将所有内部值添加到实例列表中。
是否可以实际附加跳过级别的名称,以便我可以通过my_class.lesson.price
,myclass.club.price
代替myclass.price
答案 0 :(得分:3)
您必须更改当前使用的API。这是更正后的代码:
class Event
#attr_reader :datetime, :duration, :class, :price, :level
def init(data, stack = [])
data.each do |name, value|
if value.is_a? Hash
init(value, stack << name.to_s)
stack.pop
else
new_name = stack.empty? ? name : stack.join("_") + "_" + name.to_s
instance_variable_set("@#{new_name}", value)
self.class.send(:attr_accessor, new_name)
end
end
end
end
这是以下想法:
recursion
无论如何都不会使用堆栈来使用密钥。pop
)。将所有内容附加在一起的代码很难看,但它确实有用。使用示例数据后的输出:
irb(main):042:0> e.init(data)
=> {:datetime=>"2011-11-23", :duration=>"90", :lesson=>{:price=>"7", :level=>"all"}, :club=>{:price=>"4"}}
irb(main):043:0> e
=> #<Event:0x2628360 @datetime="2011-11-23", @duration="90", @lesson_price="7", @lesson_level="all", @club_price="4">