2009-06-16 16 views
0

Ich entwickle einen Online-Shop, und der Kunde benötigt die Möglichkeit, eine Bestellung zu löschen und seine Produkte automatisch aufzufüllen (z. B. für Testaufträge). Hier ist mein erster Versuch dies bei der Umsetzung:Sind Aliasing-Methoden verpönt?

class Order < ActiveRecord::Base 
    def destroy_and_restock 
    restock_products 
    destroy 
    end 

    protected 

    def restock_products 
    line_items.each do |li|  
     li.product.quantity_on_hand += li.quantity 
     li.product.save 
    end 
    end 
end 

Aber was, wenn ich brauche, später eine andere destroy_and_x Methode zu schaffen? Warum nicht zulassen, dass X als Parameter an die destroy() Methode weitergegeben wird? So, jetzt denke ich daran zu gehen:

Dies ist mehr erweiterbar, aber macht mich etwas schmutzig. Bin ich falsch, mich schmutzig zu fühlen? Gibt es einen besseren Weg, dies zu tun?

+1

Was ist X? Das macht keinen Sinn. Wie viele Xs wird es geben? Lassen Sie sich nicht dazu verleiten, die Dinge ausnahmslos erweiterbar zu machen. – whatsisname

+0

Sorgen Sie für Erweiterbarkeit, wenn Sie sie brauchen. Es ist schwer zu wissen, was zu erweitern ist, bis Sie einen realen Fall haben. –

+0

X könnte "Erstattung", ich nehme an (wie in @ order.destroy_and_refund). –

Antwort

2

Ich würde sagen "Ja, das ist dreckig." Sie beabsichtigen nicht, das Verhalten der Methode 'destroy' zu ändern, sondern einige domänenspezifische Arbeiten auszuführen. Führen Sie dann destroy aus. Ihr erster Ansatz ist großartig - definieren Sie eine Methode, die das tut, was Sie wollen, und rufen Sie destroy nach Bedarf auf. Ich denke, dass das "Wrapping" oder "Affe-Patchen" einer Methode, wie du denkst, eine Technik ist, die am besten angewendet wird, wenn Standard-OO-Ansätze nicht verwendet werden können - zB wenn du Verhalten in einem ändern/verbessern musst Klasse, die außerhalb Ihres Kontrollbereichs definiert und verwendet wird.

Auch wenn Sie sind unter Berücksichtigung des Verhaltens der selbst destroy Verfahren zu modifizieren, würde ich zwingende die Methode hier vorschlagen, anstatt es zu wickeln:

def destroy(options = {}) 
    restock_products if options['restock'] 
    super() # I think parens are necessary here, to avoid passing options up the chain 
end 
+0

Zunächst ist Ihre Implementierung des "schmutzigen" Weges offensichtlich viel besser als meiner. Zweitens bin ich mir nicht sicher, ob meine "Absicht ist, das Verhalten der" Zerstörungsmethode "nicht zu modifizieren - versuche ich nicht" wirklich ", die Zerstörungsmethode dazu zu bringen, Parameter zu nehmen? –

+0

Ich füge hinzu: das Überschreiben der Methode wäre besser geeignet, wenn Sie sicherstellen wollten, dass IMMER etwas passiert ist, als das Destroy aufgerufen wurde - aber das würde immer noch kein Aliasing erfordern. Ein Hinweis, dass Sie nicht überschreiben sollten/Aliasing: Ihr "optionaler" Optionsparameter würde niemals vom ActiveRecord-Framework übergeben werden, wenn er 'destroy' für Sie aufruft. Nur ein sachkundiger Anrufer würde wissen, wie die Optionen übergeben werden, sodass sie entsprechend eine andere Methode verwenden könnten. – joshng

+0

Unsere Kommentare überschnitten sich, also antworte ich jetzt auf Ihre :-). Nein, ich glaube nicht, dass Sie wirklich das Verhalten von 'zerstören' verändern wollen. Sie möchten neue Verhaltensweisen hinzufügen, die das Ausführen des vorhandenen Verhaltens "zerstören" einschließen. Bedenken Sie: Sie könnten Ihre Idee auf die Spitze treiben, und schreiben Sie einfach eine Methode, die alles in der Klasse tut (sagen wir es nennen ... "senden" ;-). Wechseln Sie dann basierend auf den "Optionen", um zu entscheiden, was zu tun ist. – joshng

0

Wie wäre es nur einen Block verwenden? Dann müssen Sie nicht Ihr Haar auseinander zu ziehen, während dies in der Klasse der Gestaltung und Sie können mehr tun, wie und wann Sie müssen:

def destroy_after &block 
    yield if block 
    destroy 
end 

Dann ist dieses es wie nennen:

order.destroy_after { order.restock_products } 

Ich kann nicht Denken Sie an einen guten Namen für diese Funktion ... aber ich hoffe, Sie bekommen die Idee.

+0

Ein Problem hier ist, dass ich nicht an einen Grund denken kann, den Sie recovery_products() außerhalb des Kontextes von destroy() wünschen würden, und so dachte ich, dass ich retock_products() schützen würde (was ich nicht konnte) t machen mit Ihrer Lösung). –

+0

Ich sehe nicht, was dieser Ansatz erreicht ... Sie könnten auch nur den Block außerhalb ausführen, dann rufen Sie an: order.restock_products order.destroy – joshng

+0

err ... Formatierung verloren. order.restock_products; order.zerstören – joshng

0

Horace, ich habe deine Frage missverstanden. Ich glaube, Sie für diese suchen:

http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

Jetzt können Sie Ihre Methode halten geschützt und so viele before_destroy Dinge hinzufügen, wie Sie möchten. Hoffe das funktioniert für dich ohne zu zerstören.

Viel Glück.

0

Wenn Monkey Patching Sie nachts nicht schlafen lässt, können Sie dasselbe durch Unterklassen erreichen. Wenn ich einen schnellen Hack oder einen schnellen Debug-Hack brauche, mache ich auch einen Affen-Patch.

Verwandte Themen