21

我正在尝试从散列(带有嵌套散列)生成 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

但我找不到这样做的方法:(

4

3 回答 3

40

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

    self.class.send(:attr_accessor, name)

我建议您@在此行添加:

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

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

    data = {:datetime => '2011-11-23', :duration => '90', :class => {:price => '£7', :level => 'all'}}
于 2011-09-23T10:56:53.910 回答
5

您可以使用 method_missing 做一些元魔法来解决这个问题:

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 修改整个类。

于 2011-09-23T11:01:26.707 回答
3

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

举个例子:

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

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

于 2011-09-23T10:59:22.223 回答