Yok Et ve Sil arasındaki fark


210

Arasındaki fark nedir

@model.destroy ve @model.delete

Örneğin:

Model.find_by(col: "foo").destroy_all
//and
Model.find_by(col: "foo").delete_all

Birini veya diğerini kullanmam gerçekten önemli mi?

Yanıtlar:


289

Temelde destroy, modelde geri çağrıları çalıştırmaz, ancak deleteçalışmaz.

Gönderen Raylar API :

  • ActiveRecord::Persistence.delete

    Veritabanındaki kaydı siler ve hiçbir değişiklik yapılmaması gerektiğini (kalıcı olamayacağı için) bu örneği dondurur. Dondurulmuş örneği döndürür.

    Satır, kaydın birincil anahtarındaki SQL DELETE deyimiyle kaldırılır ve geri arama yapılmaz.

    Nesnenin before_destroy ve after_destroy geri çağrılarını veya herhangi bir: bağımlı ilişkilendirme seçeneğini zorlamak için #destroy kullanın.

  • ActiveRecord::Persistence.destroy

    Veritabanındaki kaydı siler ve hiçbir değişiklik yapılmaması gerektiğini (kalıcı olamayacağı için) bu örneği dondurur.

    Destroy ile ilişkili bir dizi geri arama var. Before_destroy geri dönüşü false değerini döndürürse, eylem iptal edilir ve imha yanlış değerini döndürür. Daha fazla bilgi için ActiveRecord :: Geri Aramalara bakınız.


Merhaba @ user740584 - Cevabınız için teşekkürler. "Modelde geri arama yapar" ile ne demek istiyorsun?
BKSpurgeon

3
@BKSpurgeon, ActiveRecord :: Callbacks: api.rubyonrails.org/classes/ActiveRecord/Callbacks.html anlamına gelir . Böyle bir geri arama, belirli koşullar altında model#before_destroyson destroy()çağrıyı durdurmak için kullanılabilir .
Todd

102

delete yalnızca geçerli nesne kaydını db'den siler, ancak ilişkili alt kayıtlarını db'den silmez.

destroy geçerli nesne kaydını db'den ve ilişkili çocuk kaydını db'den siler.

Kullanımları gerçekten önemlidir:

Birden çok üst nesneniz ortak alt nesneleri paylaşıyorsa destroy, belirli üst nesneyi çağırmak , diğer birden çok üst öğe arasında paylaşılan alt nesneleri siler.


5
Mükemmel cevap. teşekkür ederim. terminolojinin anladığım kadarıyla çocukların "öldürüldüğünü" de ekliyorum. acımasız bebek öldürme.
BKSpurgeon

Üretimde çoğu durumda 'destroy' kullanmak istiyorsunuz
Outside_Box

Hayır, bu gerekli değildir.
Taimoor Changaiz

Ne için kullanıyor olmalıdır kelime düşünüyorum destroyolduğu soyundan değil, çocuklar : dokümantasyon, imha göre "nitelikler gelen yeni bir nesne oluşturur ve daha sonra aramaları üzerine yok eder." rubydoc.info/docs/rails/4.1.7/ActiveRecord%2FRelation:destroy
Marco Lackovic

12

Bir nesneyi çağırdığınızda destroyveya destroy_allbir ActiveRecordnesnede ActiveRecordbaşlattığınızda, 'imha' işlemi başlatılır, sildiğiniz sınıfı analiz eder, bağımlılıklar için ne yapması gerektiğini belirler, doğrulamalarla çalışır vb.

Bir nesneyi çağırdığınızda deleteya delete_allda bir nesne üzerinde ActiveRecordçalıştırdığınızda , yalnızca db'ye DELETE FROM tablename WHERE conditionskarşı sorguyu çalıştırmaya çalışır ve başka ActiveRecorddüzeyli görevler gerçekleştirmez.


4

Evet, iki yöntem arasında büyük bir fark vardır Kayıtların model geri çağrıları çağrılmadan hızla silinmesini istiyorsanız delete_all komutunu kullanın

Modellerinizin geri çağrılarını önemsiyorsanız destroy_all kullanın

Resmi dokümanlardan

http://apidock.com/rails/ActiveRecord/Base/destroy_all/class

destroy_all (koşullar = nil) herkese açık

Her kaydı somutlaştırarak ve destroy yöntemini çağırarak kayıt eşleştirme koşullarını imha eder. Her nesnenin geri çağrıları yürütülür (aşağıdakilere bağlıdır: bağımlı ilişkilendirme seçenekleri ve before_destroy / after_destroy Observer yöntemleri). Yok edilen nesnelerin koleksiyonunu döndürür; her biri, hiçbir değişiklik yapılmaması gerektiğini (kalıcı olamayacakları için) dondurmak için dondurulur.

Not: Birden fazla kaydı bir defada kaldırırken örnekleme, geri arama yürütme ve her kaydın silinmesi zaman alabilir. Kayıt başına en az bir SQL DELETE sorgusu oluşturur (veya geri aramalarınızı zorlamak için muhtemelen daha fazla). Dernekleri veya geri çağrıları için endişe etmeden birçok satırı hızlı bir şekilde silmek istiyorsanız, bunun yerine delete_all öğesini kullanın.


2

Temel olarak "sil" kaydı silmek için doğrudan veritabanına bir sorgu gönderir. Bu durumda Rails, kayıtta hangi niteliklerin silindiğini veya geri arama (örneğin before_destroy) olup olmadığını bilmez .

"Destroy" yöntemi iletilen kimliği alır, "find" yöntemini kullanarak modeli veritabanından alır ve ardından destroy'i çağırır. Bu, geri aramaların tetiklendiği anlamına gelir.

Geri aramaların tetiklenmesini istemiyorsanız veya daha iyi bir performans istiyorsanız "sil" seçeneğini kullanmak istersiniz. Aksi takdirde (ve çoğu zaman) "yok et" i kullanmak istersiniz.


2

Şimdiden birçok cevap; biraz daha fazla atlamak istedim.

dokümanlar :

Has_many için destroy ve destroy_all her zaman kaldırılan kayıtların yok etme yöntemini çağırır, böylece geri çağrılar çalıştırılır. Ancak delete ve delete_all, silme işlemini: bağımlı seçenek tarafından belirtilen stratejiye göre yapar veya hayır: bağımlı seçenek belirtilmezse, varsayılan stratejiyi izler. Varsayılan strateji, has_many: içinden, varsayılan stratejinin delete_all olduğu (geri aramalarını çalıştırmadan birleştirme kayıtlarını silin) ​​dışında hiçbir şey yapmamaktır (ana kimlikleri ayarlanmış yabancı anahtarları ayarlanmış olarak bırakın).

deleteVerbage için farklı çalışır ActiveRecord::Association.has_manyve ActiveRecord::Base. İkincisi için, silme işlemi SQL DELETEtüm doğrulamaları / geri aramaları yürütür ve atlar. İlki :dependent, ilişkilendirmeye geçirilen seçeneğe göre yürütülür . Ancak, test sırasında, geri çağrıların yalnızca çalıştırıldığı deleteve çalışılmadığı aşağıdaki yan etkiyi buldumdelete_all

dependent: :destroy Misal:

class Parent < ApplicationRecord
   has_many :children,
     before_remove: -> (_) { puts "before_remove callback" },
     dependent: :destroy
end

class Child < ApplicationRecord
   belongs_to :parent

   before_destroy -> { puts "before_destroy callback" }
end

> child.delete                            # Ran without callbacks
Child Destroy (99.6ms)  DELETE FROM "children" WHERE "children"."id" = $1  [["id", 21]]

> parent.children.delete(other_child)     # Ran with callbacks
before_remove callback
before_destroy callback
Child Destroy (0.4ms)  DELETE FROM "children" WHERE "children"."id" = $1  [["id", 22]]

> parent.children.delete_all              # Ran without callbacks
Child Destroy (1.0ms)  DELETE FROM "children" WHERE "children"."parent_id" = $1  [["parent_id", 1]]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.