2014-02-05 4 views
8

Ich habe einen Datensatz in meiner Rails App mit einem after_destroy Haken, der tun muss, beachten Sie, warum der Datensatz zerstört wird. Genauer gesagt, wenn der Datensatz in einer Kaskade zerstört wird, weil sein Elternteil dependent: :destroy sagt, muss er Dinge anders machen, als wenn der Datensatz einzeln zerstört würde.In Schienen, Wie zu bestimmen, ob ein Datensatz von einem abhängigen zerstört wurde:: Rückruf zerstören?

Was ich versucht habe, ist zu sehen, ob sein Elternteil war destroyed?, nur um herauszufinden, dass dependent: :destroy Rückrufe durchgeführt werden, bevor der Elternteil zerstört wird. Das macht Sinn, weil es scheitern kann. (d. h. einschränken).

Also, wie mache ich das?

+0

@eabraham Wie ich in meiner Frage geschrieben: Was ich versucht wurde, zu tun ist, um zu sehen, ob seine Eltern '' zerstört, nur um herauszufinden, dass 'abhängig:?: Destroy' Rückrufe erledigt sind bevor der Elternteil zerstört wird. Mit anderen Worten: das ist nutzlos, die paren't kann nicht zerstört werden, da der abhängige Callback ausgegeben wird, bevor der Elternteil zerstört wird. –

Antwort

3

Eine Möglichkeit, dies zu tun, ist die Verwendung der before_destroy Callback im übergeordneten Objekt, um alle untergeordneten Objekte als durch Eltern zerstört zu zerstören. Wie sein:

class YourClass 
    before_destroy :mark_children 

    ... 
    ... 

    def mark_children 
    [:association1, :association2].each do |association| # Array should inclue association names that hate :dependent => :destroy option 
     self.send(association).each do |child| 
     # mark child object as deleted by parent 
     end 
    end 
    end 
end 

können Sie auch Active Reflections verwenden automatisch zu bestimmen, welche Verbände als :dependent => :destroy gekennzeichnet sind. Dies ist hilfreich, wenn Sie diese Funktion in vielen Klassen benötigen.

+0

prepend: true Option ist erforderlich. Siehe http://stackoverflow.com/a/23113153/513554 – Tsutomu

4

Lösung # 1

Wenn Ihr Modell einfach genug ist, und Sie brauchen keine Rückrufe in der Kind-Beziehung berufen, die Sie gerade dependent: delete_all in der übergeordneten verwenden können.

Lösung # 2

Für komplexere Szenarien Sie destroyed_by_association verwenden können, das gibt ein ActiveRecord::Reflection::HasManyReflection Objekt, wenn es Teil der Kaskade ist, oder null sonst:

after_destroy :your_callback 

def your_callback 
    if destroyed_by_association 
    # this is part of a cascade 
    else 
    # isolated deletion 
    end 
end 

ich das gerade versucht, in Rails 4.2 und es funktioniert.

Quelle: https://github.com/rails/rails/issues/12828#issuecomment-28142658

Verwandte Themen