Выполните метод после выбора переменных в Ruby - PullRequest
1 голос
/ 09 января 2012

Я пытаюсь высушить некоторый код, и я чувствую, что назначение переменных в Ruby должно помочь упростить это. У меня есть класс с определенным количеством различных переменных экземпляра. Некоторые из них предназначены для скрытого (или только для чтения), но многие являются общедоступными, с доступом для чтения / записи.

Для всех переменных с открытым доступом для записи я хочу выполнять определенный метод после каждого присваивания. Я знаю, что, в общем, я могу сделать это:

def foo=(new_foo)
    @foo = new_foo
    post_process(@foo)
end

def bar=(new_bar)
    @bar = new_bar
    post_process(@foo)
end

Однако, похоже, должен быть хороший способ высушить это, так как я делаю по существу одно и то же после каждого присваивания (то есть запускаю один и тот же метод и передаю вновь назначенную переменную в качестве параметра этот метод). Поскольку у меня есть несколько таких переменных, было бы здорово иметь решение общего назначения.

1 Ответ

2 голосов
/ 09 января 2012

Более простое решение

Если вы назначите эти переменные в пакетном режиме, вы можете сделать что-то вроде этого:

kv_pairs = {:foo => new_foo_value,
  :bar => new_bar_value}

kv_pairs.each do |k, v|
  self.send(k.to_s + '=', v)
  post_process(v)
end

Метапрограммирование

Вот немного магии рубина: -)

module PostProcessAssignments
  def hooked_accessor( *symbols )
    symbols.each { | symbol |
      class_eval( "def #{symbol}() @#{symbol}; end" )
      class_eval( "def #{symbol}=(val) @#{symbol} = val; post_process('#{symbol}', val); end" )
    }
  end
end

class MyClass
  extend PostProcessAssignments

  hooked_accessor :foo

  def post_process prop, val
    puts "#{prop} was set to #{val}"
  end


end

mc = MyClass.new
mc.foo = 4
puts mc.foo

Выходы:

foo was set to 4
4
...