2013-06-05 15 views
12
class Post < ActiveRecord::Base 
    has_many :posts_tags 
    has_many :tags, through: :posts_tags 
end 

class PostsTag < ActiveRecord::Base 
    belongs_to :post 
    belongs_to :tag 
end 

class Tag < ActiveRecord::Base 
    has_many :posts_tags 
    has_many :posts, through: :posts_tags 
end 

Quando Post viene eliminato, desidero eliminare anche tutte le sue associazioni. NON voglio le convalide sul modello PostsTag da eseguire. Voglio solo cancellato.Modo corretto per cancellare has_many: through join records?

Ho riscontrato che l'aggiunta di una dipendenza dalla relazione ai tag Post dal modello Post funziona come voglio: has_many :posts_tags, dependent: :delete_all.

Tuttavia, la documentazione sull'argomento sembra suggerire che dovrei farlo invece: has_many :tags, through: :posts_tags, dependent: :delete_all. Quando faccio questo, l'oggetto Tag viene distrutto e l'oggetto join rimane.

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many

Per has_many, distruggere sempre chiamare il metodo distruggere del record (s) essendo rimosso in modo che callback vengono eseguiti. Tuttavia, l'eliminazione eseguirà l'eliminazione in base alla strategia specificata dall'opzione: dipendente o, in caso contrario, l'opzione dipendente seguirà la strategia predefinita. La strategia predefinita è: nullify (imposta le chiavi esterne su zero), eccetto has_many: through, dove la strategia predefinita è delete_all (elimina i record di join, senza eseguire i callback).

  1. Come posso avere la strategia predefinita effettivamente utilizzato? Se esco: dipendente completamente, nessun record viene rimosso. E non posso solo indicare: dipende da una relazione has_many. Rails ritorna e dice "L'opzione: dependent prevede: destroy,: delete_all,: nullify or: restrict ({})".
  2. Se non specificare: dipende uno dei rapporti, che non annulla il post_id sull'oggetto PostsTag come sembra suggerire

Forse sto leggendo questo torto e l'approccio che ho trovato funziona è il modo corretto?

+1

Cosa succede se un tag viene utilizzato da più post? Se un post viene eliminato, gli altri post saranno interessati. –

+0

true e Tag dovrebbe avere "has_many: posts, through:: posts_tags' not posts, userei' has_many: posts_tags, dependent:: destroy' per eliminare posts_tag e lasciare i tag da solo. È possibile eliminare tag orfani con un'attività rake o console. – rmagnum2002

+0

Risolto l'associazione, grazie. Sto solo cercando di capire la documentazione.La formulazione è confusa – Brian

risposta

17

La tua idea originale:

has_many :posts_tags, dependent: :delete_all 

è esattamente quello che vuoi. Si fa non si desidera dichiararlo sull'associazione has-many-though :tags, in quanto ciò distruggerà tutti i Tag associati. Ciò che si desidera eliminare è l'associazione stessa, ovvero ciò che rappresenta il modello di join PostTag.

Quindi perché i doc dicono quello che fanno? Stai incomprensione lo scenario che la documentazione sta descrivendo:

Post.find(1).destroy 
Post.find(1).tags.delete 

La prima chiamata (lo scenario) sarà semplicemente distruggere il Post. Cioè, a meno che tu non specifichi una strategia :dependent, come ti suggerisco di fare. La seconda chiamata è ciò che la documentazione sta descrivendo. Chiamare .tags.delete non distruggerà (di default) i tag (poiché sono uniti da has-many-through), ma il modello di join associato che unisce questi tag.

+0

ahh, grazie che ha molto più senso – Brian

Problemi correlati