Ok, also habe ich meinen Code in meiner kleinen Rails App umstrukturiert, um Duplikate zu entfernen, und im Allgemeinen mein Leben einfacher zu machen (wie ich ein einfaches Leben mag). Teil dieses Refactorings war es, Code, der zwei meiner Modelle gemeinsam hat, in ein Modul zu verschieben, das ich dort einfügen kann, wo ich es brauche.Ruby Mixins und Calling Super Methoden
So weit, so gut. Sieht so aus, als würde es klappen, aber ich habe gerade ein Problem gefunden, von dem ich nicht weiß, wie ich es schaffen soll. Das Modul (das ich als sendbar bezeichnet habe) ist nur der Code, der das Faxen, E-Mailen oder Drucken eines PDFs des Dokuments übernimmt. So habe ich zum Beispiel eine Bestellung und ich habe interne Verkaufsaufträge (imaginativ abgekürzt zu ISO).
Das Problem, das ich getroffen habe, ist, dass ich einige Variablen initialisiert werden soll (für Menschen initialisiert, die buchstabieren nicht korrekt: P), nachdem das Objekt geladen wird, so habe ich die after_initialize Haken verwendet worden. Kein Problem ... bis ich anfange, weitere Mixins hinzuzufügen.
Das Problem, das ich habe, ist, dass ich ein after_initialize
in einem meiner Mixins haben kann, so brauche ich einen Super Anruf am Start sind die anderen mixin after_initialize
Anrufe aufgerufen, um sicherzustellen, erhalten . Was toll ist, bis ich am Ende super anrufe und ich einen Fehler bekomme, weil es keinen Super zu callen gibt.
Hier ist ein kleines Beispiel für den Fall, habe ich nicht genug ist verwirrend:
class Iso < ActiveRecord::Base
include Shared::TracksSerialNumberExtension
include Shared::OrderLines
extend Shared::Filtered
include Sendable::Model
validates_presence_of :customer
validates_associated :lines
owned_by :customer
order_lines :despatched # Mixin
tracks_serial_numbers :items # Mixin
sendable :customer # Mixin
attr_accessor :address
def initialize(params = nil)
super
self.created_at ||= Time.now.to_date
end
end
Also, wenn jeder der Mixins einen after_initialize Anruf haben, mit einem Super Anruf, wie kann ich aufhören dass letzte Super Anruf von der Erhöhung des Fehlers? Wie kann ich testen, ob die Super-Methode existiert, bevor ich sie anrufe?
downvoted, weil es keine allgemeine Lösung. Der Punkt ist, dass Sie nicht wissen, ob das Super existiert oder nicht, so dass ActiveRecord :: Base # nach dem Initialisieren monkeypatching, erstellen Sie einen Punkt, wo Ihr Code bricht, wenn ActiveRecord eine Base # nach_initialisieren, oder seine Arity geändert wird ; es ist viel besser, es bedingungslos zu nennen, wenn es definiert ist. – yaauie
@yaauie - sicher, ich hätte eine 'raise 'oh nein' wenn Methoden.include? (: After_initialize)' vor dem Monkeypatch, aber das würde das Beispiel schwerer zu verstehen machen ... Es ist so einfach, eingeholt zu werden in der Detaillierung aller Randfälle, die die eigentliche Lektion hier (patch einfach eine Basismethode in) würde im Rauschen verloren gehen. –
Monkeypatching ist keine allgemeine Lösung und sollte im Allgemeinen nicht gefördert werden. Eine Antwort, die einen einmaligen Monekypatch enthält, der möglicherweise funktionieren kann, führt zu unnötig komplexem und fragilem Code, insbesondere wenn Sie die gesamte Vererbungskette nicht kontrollieren können. – yaauie