Frage

Ok, also habe ich die Umgestaltung mein code in meiner kleinen Rails-app in einem Versuch zu entfernen, Vervielfältigung, und im Allgemeinen machen mein Leben leichter (als ich wie ein leichtes Leben).Teil dieser Umgestaltung wurde zum verschieben von code, die ist üblich, zwei meiner Modelle zu einem Modul, das kann ich zählen, wo ich Sie brauche.

So weit, So gut.Sieht aus wie es funktionieren wird, aber ich habe gerade ein problem, dass ich nicht sicher bin, wie man das umgehen kann.Das Modul (die ich genannt habe verschickbar), ist nur der code, der Griffe, Faxen, e-mailen oder drucken einer PDF-Datei des Dokuments.So, ich habe zum Beispiel eine Bestellung, und ich habe die Interne Aufträge (phantasievoll abgekürzt ISO).

Das problem, das ich habe, aufgefallen ist, ist, dass ich möchte einige Variablen initialisiert (initialisiert für Leute, die nicht buchstabieren richtig :P ), nachdem das Objekt geladen wurde, also habe ich mit der after_initialize Haken.Kein problem...bis ich starten Sie das hinzufügen einiger mehr Mixins in Verbindung.

Das problem, das ich habe, ist, dass ich eine after_initialize in einem meiner Mixins in Verbindung, so dass ich brauchen, um ein super rufen Sie beim start, stellen Sie sicher, dass das andere mixin after_initialize Anrufe aufgerufen.Das ist toll, bis ich am Ende dem Aufruf von super und ich bekomme einen Fehler, weil es ist keine super zu rufen.

Hier ein kleines Beispiel, im Fall ich noch nicht verwirrend genug:

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 in Verbindung eine after_initialize nennen, mit einem super aufrufen, wie kann ich verhindern, dass last super rufen Sie aus, das den Fehler?Wie kann ich testen, dass die super-Methode vorhanden ist, bevor ich es nennen?

War es hilfreich?

Lösung

Sie können dies verwenden:

super if defined?(super)

Hier ist ein Beispiel:

class A
end

class B < A
  def t
    super if defined?(super)
    puts "Hi from B"
  end
end

B.new.t

Andere Tipps

Haben Sie versucht, alias_method_chain?Grundsätzlich können Sie alle Ihre angekettet after_initialize Anrufe.Es wirkt wie ein Dekorateur:jede neue Methode fügt eine neue Ebene von Funktion und übergibt die Kontrolle an die "außer Kraft gesetzt" - Methode, um den rest zu tun.

Die inklusive Klasse (die Sache, die erbt von ActiveRecord::Base, die in diesem Fall ist Iso) könnte definieren Sie Ihre eigenen after_initialize, so dass jede andere Lösung als alias_method_chain (oder andere aliasing-Effekt, spart das original) Risiken überschreiben code.@Orion Edwards' Lösung ist die beste, die ich mit oben kommen kann.Es gibt andere, aber Sie sind weit mehr hackish.

alias_method_chain hat auch den Vorteil, erstellen genannten Versionen der after_initialize-Methode, das heißt, Sie können die Anruf, um in den seltenen Fällen, dass es darauf ankommt.Andernfalls bist du auf Gedeih und Verderb, was auch immer, um die inklusive Klasse umfasst die Mixins in Verbindung.

später:

Ich habe eine Frage zu dem ruby-on-rails-core-mailing-Liste, über die Erstellung von Standard -, leer-Implementierungen aller Rückrufe.Der Speichervorgang überprüft für Sie sowieso alle, also ich sehe nicht ein, warum Sie nicht da sein sollte.Der einzige Nachteil ist die Schaffung von zusätzlichen leeren stack-frames, aber das ist ziemlich Billig auf jede bekannte Umsetzung.

Sie können nur werfen eine schnelle bedingte es:

super if respond_to?('super')

und Sie sollten in Ordnung sein - kein hinzufügen von nutzlosen Methoden;schön und sauber.

Anstatt zu überprüfen, ob die super-Methode vorhanden ist, können Sie einfach definieren, es

class ActiveRecord::Base
    def after_initialize
    end
end

Dies funktioniert in meinen Tests, und sollte nicht Pause Ihre vorhandenen code, da alle anderen Klassen, die definieren, es wird einfach automatisch überschreiben dieser Methode sowieso

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top