2010-10-29 5 views
36

Ho esaminato le guide di Ruby on Rails e non riesco a capire come impedire a qualcuno di eliminare un record padre se ha figli. Per esempio. Se il mio database ha CLIENTI e ogni cliente può avere più ORDINI, voglio impedire a qualcuno di eliminare un cliente se ha ordini nel database. Dovrebbero essere in grado di eliminare un cliente solo se non ha ordini.Come si impedisce la cancellazione del genitore se ha record figlio?

Esiste un modo per definire l'associazione tra i modelli per applicare questo comportamento?

risposta

43

Si potrebbe fare questo in un callback:

class Customer < ActiveRecord::Base 
    has_many :orders 
    before_destroy :check_for_orders 

    private 

    def check_for_orders 
    if orders.count > 0 
     errors.add_to_base("cannot delete customer while orders exist") 
     return false 
    end 
    end 
end 

EDIT

vedono this answer di un modo migliore per fare questo.

+5

Questo è il modo migliore. È il più pulito, ed è esattamente dove cerco un filtro del genere se lavorassi sul tuo codice. Restituire "false" nella richiamata è ciò che indica ai binari di non procedere con l'azione. –

+0

'has_any ...?' :) –

+0

Grazie, Joe. No, non ho inventato un nuovo tipo di associazione ... – zetetic

0

Provare a utilizzare filters per collegare codice personalizzato durante l'elaborazione della richiesta.

0

Una possibilità sarebbe evitare di fornire agli utenti un collegamento alla cancellazione in questo scenario.

link_to_unless [email protected]? 

Un altro modo sarebbe quello di gestire questo nel controllore:

if [email protected]? 
    flash[:notice] = "Cannot delete a customer with orders" 
    render :action => :some_action 
end 

Oppure, come suggerisce Joe, before_filters potrebbero funzionare bene qui e probabilmente sarebbe un modo molto più secco di fare questo, soprattutto se vuoi questo tipo di comportamento per più modelli di un semplice Cliente.

81
class Customer < ActiveRecord::Base 
    has_many :orders, :dependent => :restrict # raises ActiveRecord::DeleteRestrictionError 

Edit: come di Rails 4.1, :restrict non è un'opzione valida, e invece si dovrebbe utilizzare :restrict_with_error o :restrict_with_exception

Eg .:

class Customer < ActiveRecord::Base 
    has_many :orders, :dependent => :restrict_with_error 
+0

Grazie! Pulito;) Ho pensato che ref. l'integrità era attiva per impostazione predefinita in Rails ... – luigi7up

+1

È possibile personalizzare il messaggio di restrizione? –

+2

Questa risposta può essere aggiornata per riflettere le modifiche in Rails 4.1 e versioni successive? Msgstr "Rimosso il supporto per l'opzione deprecata: limitazione per: dipendente nelle associazioni". http://edgeguides.rubyonrails.org/4_1_release_notes.html. L'opzione: dependent deve essere una delle seguenti: [destroy,: delete_all,: nullify,: restrict_with_error,: restrict_with_exception] – Marklar