Ruby:动态生成attribute_accessor

我正在尝试从散列(使用嵌套散列)生成attr_reader,以便它自动镜像instance_variable创建。

这是我到目前为止:

data = {:@datetime => '2011-11-23', :@duration => '90', :@class => {:@price => '£7', :@level => 'all'}} 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) #bit missing: attr_accessor name.to_sym end end end 

但我找不到办法做到这一点:(

您需要在Event类上调用(private)类方法attr_accessor

  self.class.send(:attr_accessor, name) 

我建议你在这一行添加@

  instance_variable_set("@#{name}", value) 

并且不要在哈希中使用它们。

  data = {:datetime => '2011-11-23', :duration => '90', :class => {:price => '£7', :level => 'all'}} 

你可以使用method_missing做一些meta-magic来解决这个问题:

 class Event def method_missing(method_name, *args, &block) if instance_variable_names.include? "@#{method_name}" instance_variable_get "@#{method_name}" else super end end end 

这样做是允许通过object.variable语法访问对象实例变量,如果对象定义了那些变量,而不需要通过attr_accessor修改整个类。

attr_accessor是一个类方法,因此需要在类上调用。 它也是一个私有方法,因此您需要在类对象为self的上下文中调用它。

举个例子:

 class C def foo self.class.instance_eval do attr_accessor :baz end end end 

在创建一个C实例并在该实例上调用foo ,该实例 – 以及所有未来的实例 – 将包含方法bazbaz=