2016-06-01 6 views
1

Ich habe eine trashable Sorge, die es einem Benutzer ermöglicht, bestimmte Dinge zu löschen ("löschen").Modellverknüpfung mit einem Bereich für trashable Modul

Das Problem ist, dass, obwohl das Element verworfen werden kann, es immer noch referenziert werden muss, wenn Sie etwas älter anzeigen. Wenn Sie das jetzt tun, wird es das Objekt nicht finden, da ich die default_scope geändert habe, um nur zu zeigen, wo der Papierkorb falsch ist.

Hier ist mein trashable Modul:

module Trashable 
    extend ActiveSupport::Concern 

    included do 
    default_scope { where(trashed: false) } 
    scope :trashed, -> { unscoped.where(trashed: true) } 
    validates :trashed, inclusion: { in: [true, false] } 
    end 

    def trash 
    update_attribute :trashed, true 
    end 
end 

jetzt habe ich ein Order Modell, in dem Sie eine Bestellung anzeigen können. Wenn wir zum Beispiel ein Produkt ausrangieren, möchte ich immer noch, dass der Benutzer seine Bestellung einsehen und das Produkt sehen kann.

Jetzt bin ich nicht in der Lage, dass für den Zugriff mit einem Modell Verein wie:

has_many :products und macht es so, dass es sowohl in dem Trashed ist falsch und wahr.

Weiß jemand, wie man das erreicht?

+0

Ich denke, dass Sie mit diesem [Edelstein] gehen können (https://github.com/ActsAsParanoid/acts_as_paranoid) –

+0

aber können Sie das explizit angeben: 'has_many: Produkte, {unscope (: wo) .where trashed: [ wahr, falsch]} '? –

Antwort

1

Sie können dies durch mehrere Wege zu erreichen, hier ist das, was ich weiß,

Lösung 1with_trashed definieren wie folgt aus:

module Trashable 
    extend ActiveSupport::Concern 

    included do 
    default_scope { where(trashed: false) } 
    scope :trashed, -> { unscoped.where(trashed: true) } 

    # Define a new scope here 
    scope :with_trashed, -> { unscope(where: :trashed) } 
    validates :trashed, inclusion: { in: [true, false] } 
    end 

    def trash 
    update_attribute :trashed, true 
    end 
end 

Dann können Sie es mögen:

order.products.with_trashed 

Lösung 2 Unbeschnittene Klasse definieren

class UnscopedProduct < Product 
    self.default_scopes = [] 
    belongs_to :order 
end 

class Order < ActiveRecord::Base 
    has_many :products 
    has_many :unscoped_products, foreign_key: :order_id, class_name: "UnscopedProduct" 
end 

Dann können Sie es gerne verwenden:

order.unscope_products 

Als meine Erfahrung würde ich Lösung verwenden 1, aber es gibt einige seltsamen Fälle, dies funktioniert nicht mehr, zum Beispiel in einem komplexen Abfrage, also merken Sie sich Lösung 2, es wird viel Zeit sparen!

Die Verwendung von Default scope führt zu so vielen Problemen bei späteren komplexen Abfragen. Das hängt von dir ab!

0

Sie können ein paar Dinge tun:

  1. Als jemand im Kommentar erwähnt, sollten Sie Acts as Paranoid Gem verwenden, die genau für diesen Zweck gedacht ist. Mit diesem können Sie die Methoden with_deleted oder only_deleted verwenden, die Ihnen auch relevante gelöschte Objekte zurückgeben.

  2. Sie können nicht einfach unscoped verwenden, wie Sie oben tun. Unscoped entfernt alle Bedingungen und nicht nur trashed: false. Sie können auch versuchen, einen anderen Bereich zu erstellen, der gelöschte Objekte zurückgibt und die im zweiten Bereich gefundenen Objekte mit dem ersten zusammenführt.

scope_1_results + scope_2_results

Wenn Sie sind auf Schienen 5, können Sie auch OR die Bereiche, die nicht möglich in Rails 4.x oder weniger ist.

Verwandte Themen