Wie verwende ich die Ruby-Metaprogrammierung, um einem Rails-Modell Rückrufe hinzuzufügen?

Ich habe ein einfaches Cacheable-Modul geschrieben, mit dem es einfach ist, Aggregatfelder in einem übergeordneten Modell zwischenzuspeichern. Für das Modul muss das übergeordnete Objekt das implementierencacheable Methode und acalc_ Methode für jedes Feld, für das Caching auf übergeordneter Ebene erforderlich ist.

module Cacheable
  def cache!(fields, *objects)
    objects.each do |object|
      if object.cacheable?
        calc(fields, objects)
        save!(objects)
      end
    end
  end

  def calc(fields, objects)
    fields.each { |field| objects.each(&:"calc_#{field}") }
  end

  def save!(objects)
    objects.each(&:save!)
  end
end

Ich möchte dem ActiveRecord-Modell, in dem dieses Modul enthalten ist, Rückrufe hinzufügen. Diese Methode würde erfordern, dass das Modell einen Hash von übergeordneten Modellen und Feldnamen implementiert, die zwischengespeichert werden müssen.

def cachebacks(klass, parents)
  [:after_save, :after_destroy].each do |callback|
    self.send(callback, proc { cache!(CACHEABLE[klass], self.send(parents)) })
  end
end

Dieser Ansatz funktioniert hervorragend, wenn ich beide Rückrufe manuell hinzufüge, indem ich Folgendes verwende:

after_save proc { cache!(CACHEABLE[Quote], *quotes.all) }
after_destroy proc { cache!(CACHEABLE[Quote], *quotes.all) }

Ich erhalte jedoch die folgende Fehlermeldung, wenn ich versuche, die zu verwendencachebacks Methode, um diese zu Rückrufen hinzuzufügen.

cachebacks(Quote, "*quotes.all")

NoMethodError: undefined method `cachebacks' for #<Class:0x007fe7be3f2ae8>

Wie füge ich diese Rückrufe dynamisch der Klasse hinzu?

Antworten auf die Frage(3)

Ihre Antwort auf die Frage