2008-12-01 6 views
64

Je sais que c'est probablement sur Internet quelque part mais je ne trouve pas la réponse ici sur Stackoverflow alors j'ai pensé que je pourrais augmenter la base de connaissances ici un peu. Je suis un novice de Ruby and Rails, mais mon entreprise s'y investit assez et j'essaie d'apprendre à le connaître un peu plus en détail.Puis-je configurer la suppression de Cascade dans Rails?

Il m'est difficile de changer d'état d'esprit en concevant une application à partir du "modèle" plutôt que de la base de données, alors j'essaie de comprendre comment tout le travail de conception que je faisais classiquement la base de données dans le modèle Rails à la place.

Donc la tâche la plus récente que je me suis donné est de comprendre comment configurer un modèle de base de données Rails pour faire des suppressions en cascade? Y a-t-il un moyen facile de faire ça? Ou devrais-je aller dans le MySQL et mettre cela en place?

Merci.

-Matt

Répondre

79

Vous pouvez également définir l'option: dependent à: delete_all. : delete_all émettra une instruction SQL unique pour supprimer tous les enregistrements enfants. à cause de cela en utilisant: delete_all peut vous donner de meilleures performances.

has_many :memberships, dependent: :delete_all 
+8

Votre explication est source de confusion. Une instruction SQL unique sera utilisée, mais la méthode destroy ne sera pas appelée pour chaque ligne enfant. Vous devez utiliser destroy_all pour cela. –

+0

@John - espère que les modifications éclaircir la confusion. Merci d'avoir fait remarquer cela. –

+0

@Mike - beaucoup mieux, merci. –

58

Oui, vous pouvez, si vous utilisez une relation comme has_many vous faites juste ce

has_many :memberships, dependent: :destroy 
+0

Dan, Donc, je suppose que ma prochaine question est de savoir si je lance une commande db migrate cela va-t-il le faire dans la base de données?Ou la cascade est-elle complètement gérée par des rails? –

+0

Oui, il est géré par des rails. (Assurez-vous que vous avez vraiment toujours besoin de supprimer toutes les lignes liées, cependant.) –

+0

@Matt - la ligne has_many devrait être dans votre classe de modèle, la migration n'ajoutera pas cela pour vous. – Gareth

6

On dirait que ce plugin peut vous donner ce que vous cherchez si vous voulez la mise en cascade supprime reflète dans la structure de base de données réelle:

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

Format pour utiliser ce dans une migration serait somethi ng comme ceci:

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

Ce lien est mort mais c'est une alternative plus récente: http://github.com/matthuhiggins/foreigner – gdelfino

9

Il suffit de garder à l'esprit que delete_all ne signera pas callbacks (comme before_destroy et after_destroy) sur les dossiers des enfants.

9

Contrairement à la réponse fournie, je suggère fortement de le faire également au niveau de la base de données. Dans le cas où vous avez des processus différents ou un environnement multithread, il peut arriver que les enregistrements ne soient pas correctement supprimés. De plus, la clé étrangère de la base de données rend les choses beaucoup plus rapides lors de la suppression de beaucoup de données.

Comme dans la réponse suggérée faire ceci:

has_many :memberships, dependent: :delete_all 

Cependant Assurez-vous également d'installer un foreign_key dans une migration. De cette façon, la base de données prend soin de supprimer les enregistrements automatiquement pour vous.

Pour annuler les valeurs lorsqu'une adhésion est supprimée, en supposant avez un modèle utilisateur:

add_foreign_key :users, :memberships, on_delete: :nullify 

Vous pouvez également supprimer tous les modèles à chaque fois qu'une adhésion est supprimée

add_foreign_key :users, :memberships, on_delete: :cascade 
Questions connexes