Ruby: динамически генерировать attribute_accessor - PullRequest
20 голосов
/ 23 сентября 2011

Я пытаюсь сгенерировать 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

Но я не могу найти способ сделать это: (

Ответы [ 3 ]

35 голосов
/ 23 сентября 2011

Вам необходимо вызвать (приватный) метод класса 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'}}
3 голосов
/ 23 сентября 2011

Вы можете сделать небольшую мета-магию, чтобы решить эту проблему, используя 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.

1 голос
/ 23 сентября 2011

attr_accessor - это метод класса, поэтому его нужно вызывать в классе.Это также частный метод, поэтому его необходимо вызывать в контексте, в котором объект класса имеет вид self.

. Например:

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

После создания экземпляраC и вызов foo для этого экземпляра, этот экземпляр - и все будущие экземпляры - будут содержать методы baz и baz=.

...