Rails'de Basamaklı silme ayarlayabilir miyim?


90

Bunun muhtemelen internette bir yerlerde olduğunu biliyorum ama cevabı burada Stackoverflow'da bulamıyorum, bu yüzden buradaki bilgi tabanını biraz artırabileceğimi düşündüm.

Ruby and Rails'e yeni başlayan biriyim ama şirketim ona oldukça yatırım yapıyor, bu yüzden onu biraz daha detaylı tanımaya çalışıyorum.

Zihniyetimi veritabanından ziyade "modelden" bir uygulama tasarlamaya değiştirmek benim için zordu, bu yüzden klasik olarak veritabanında yaptığım tüm tasarım işlerini nasıl yapacağımı anlamaya çalışıyorum. Bunun yerine raylı model.

Öyleyse kendime verdiğim en son görev, bir Rails veritabanı modelini basamaklı silme işlemleri yapacak şekilde nasıl yapılandıracağımı bulmak? Bunu yapmanın kolay bir yolu var mı? Yoksa MySql'e gidip bunu ayarlamam mı gerekir?

Yanıtlar:


106

Ayrıca: bağımlı seçeneğini şu şekilde ayarlayabilirsiniz: sil_all. : delete_all, tüm alt kayıtları silmek için tek bir SQL ifadesi yayınlayacaktır. bunun nedeni: delete_all size daha iyi performans sağlayabilir.

has_many :memberships, dependent: :delete_all

8
Açıklamanız kafa karıştırıcı. Tek bir SQL ifadesi kullanılacak, ancak her alt satır için destroy yöntemi çağrılmayacaktır. Bunun için destroy_all kullanmalısınız.
John Topley

@John - düzenlemelerin karışıklığı gidermesini umuyoruz. buna işaret ettiğiniz için teşekkürler.
Mike Breen

27
Bunun için kullanmak :delete_allve bunun :destroyiçin arasındaki farkı anladığınızdan emin olun . Her ikisi de alt üyeliklerin (1 seviye silme [alıntı gerekli] ve nyok etme (çocukları bağımlı yok etme varsa)) veritabanından kaldırılmasına neden olur, ancak :destroyher bir alt nesneyi başlatır ve önce geri aramaları :delete_allçalıştırırken, doğrudan bir Veritabanındaki SQL DELETE ifadesi. :destroybu nedenle daha yavaştır, ancak bir kayıt yok edildiğinde geri arama yapmanıza izin verir. Bir uçta Rayları aşmak ve diğer yanda potansiyel n ^ x somutlaştırması.
jstim

2
Veritabanı yabancı anahtarlarını da kurmanızı öneririm. Bu şekilde kayıtlar tek bir işlemle silinir. Gönderdiğim aşağıdaki cevaba bakın.
Hendrik

66

Evet yapabilirsin, has_many gibi bir ilişki kullanıyorsanız sadece bunu yaparsınız

has_many :memberships, dependent: :destroy

Dan, sanırım bir sonraki sorum şu: bir db migrate komutu çalıştırırsam, bu gerçekten db'de bunu ayarlayacak mı? Yoksa basamaklama tamamen raylarla mı halledilir?
matt_dev

Evet, raylarla işleniyor. (Yine de her zaman ilgili satırları silmeniz gerektiğinden emin olun.)
Stein G. Strindhaug

@Matt - has_many satırı model sınıfınızda olmalıdır, geçiş bunu sizin için eklemeyecektir.
Gareth

Bu çözümü tercih ediyorum çünkü bağımlı modelin başka bir has_many ilişkisi varsa da işe yarıyor
tpei

27

Verilen cevabın aksine, bunu bir veritabanı seviyesinde yapmayı şiddetle tavsiye ediyorum. Farklı süreçleriniz veya çok iş parçacıklı bir ortamınız olması durumunda, kayıtlar düzgün şekilde silinmeyebilir. Ayrıca veritabanı yabancı anahtarı, çok sayıda veriyi silerken işleri daha hızlı hale getirir.

Önerilen cevapta olduğu gibi şunu yapın:

has_many :memberships, dependent: :delete_all

Ancak foreign_key, bir geçişte ayarladığınızdan da emin olun . Bu şekilde, veritabanı sizin için kayıtları otomatik olarak silmeyi üstlenir.

Kullanıcı modeliniz olduğunu varsayarak, üyelik silindiğinde değerleri geçersiz kılmak için:

add_foreign_key :users, :memberships, on_delete: :nullify

Ayrıca bir üyelik silindiğinde tüm modelleri silebilirsiniz.

add_foreign_key :users, :memberships, on_delete: :cascade

Yani hem "has_many: üyelikler, bağımlı:: delete_all" ve "add_foreign_key: kullanıcılar,: üyelikler, on_delete:: cascade" kullanabilir miyim? İyi çalışacak mı?
Rubycon

2
delete_allModelde kurulum yapmanıza bile gerek kalmayacak . Yabancı anahtar, veritabanı düzeyinde sizin için her şeyi düzgün bir şekilde silmeyi sağlayacaktır.
Hendrik

3
İkisini de yaptığınızda ne olacağını merak ediyorum. Olumsuz bir etkisi olmayacak gibi görünüyor, ancak bu uygulama ile hem AR hem de DB seviyesi yapma konusunda kötü bir deneyime sahip olan var mı?
James Klein

1
Veritabanı seviyesi aradığım şeydi. Bence bu kabul edilen cevap olmalı. Diğerleri yalnızca sorgularım standart ActiveRecord işlemlerine bağlı kalırsa işe yarıyor gibi görünüyor.
Brett Beatty

10

Silme_all öğesinin alt kayıtlarda herhangi bir geri arama (before_destroy ve after_destroy gibi) yürütmeyeceğini unutmayın.


6

Görünüşe göre bu eklenti, gerçek veritabanı yapısına yansıyan kademeli silme işlemlerinin olmasını istiyorsanız aradığınız şeyi size verebilir:

http://www.redhillonrails.org/foreign_key_migrations.html

Bunu bir taşıma işleminde kullanmak için format şu şekilde olacaktır:

create_table :orders do |t|
  t.column :customer_id, :integer, :on_delete => :set_null, :on_update => :cascade
  ...
end

5
Bu bağlantı kesildi
gdelfino
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.