2012-01-11 7 views
8

Ho delle spedizioni e fatture.Rails 3. before_destroy validation per evitare l'eliminazione dei record padre

fattura appartiene alla spedizione
spedizione ha una fattura

Se la spedizione ha una fattura, quindi la spedizione non dovrebbe essere in grado di essere eliminato. Devo configurarlo nei modelli perché sto usando ActiveAdmin.

Quindi ho fatto questo in shipment.rb

has_one :invoice 
before_destroy :check_for_invoice 

private 

def check_for_invoice 
    unless invoice.nil? 
    self.errors[:base] << "Cannot delete shipment while its invoice exists." 
    end 
end 

Ma ottengo solo un messaggio di giallo con scritto "La spedizione non può essere eliminato", ma è stato di fatto cancellato.

Come si impedisce la cancellazione della spedizione?

risposta

23

Il before_destroy callback ha bisogno di un valore true/false per determinare se o non proceeed.

Aggiungi un return false al check_for_invoice in questo modo:

has_one :invoice 
before_destroy :check_for_invoice 

private 

def check_for_invoice 
    unless invoice.nil?  
    self.errors[:base] << "Cannot delete shipment while its invoice exists." 
    return false 
    end 
end 
+0

Ah è vero! Ho dimenticato di restituire false. Ho anche postato questa parte del codice in modo errato "if invoice.nil?", Si suppone che sia "meno di fattura.nil?". – leonel

+0

Ero curioso della logica, ma ho pensato che potesse essere solo qualcosa di strano. Aggiornerò la mia risposta per renderla compatibile con i posteri. –

+0

Selezionare [questa risposta a una domanda simile] (http://stackoverflow.com/a/10257516/703233) per un modo migliore per farlo. – nitsas

3

Dal docs:

Se un before_ * callback restituisce false, tutti i richiami più tardi e l'azione associata vengono cancellati.

Quindi provare questo:

self.errors[:base] << "Cannot delete shipment while its invoice exists." and return false 
+0

@Jordan hai ragione che 'return' non è per lo più idiomatica in Ruby, ma cosa succede se la linea non è l'ultimo nel metodo (considerare anche il refactoring)? O cosa succede se in seguito aggiungi altre istruzioni nel metodo e dimentichi di aggiungere il reso? Penso che questi siano i motivi per cui si vede 'e return false' usati nei progetti di binari ... – maprihoda

+0

Ok, questo è un argomento abbastanza convincente. Ho ritirato la mia revisione. –

4

I miei 2 centesimi in shipment.rb

has_one :invoice, dependent: :restrict 

Penso che sarà il lavoro, ho visto questa soluzione in un altro thread. Sono in trincea ora nei miei modelli.

1

Per Rails 4:

class Shipment < ActiveRecord::Base 
    has_one :invoice, dependent: :restrict_with_error 

farà il trucco. Se si desidera un'eccezione anziché un errore, utilizzare :restrict_with_exception. Vedi di più su the relevant api docs page.

Per Rails 3 (forse prima anche) Ricerche:

class Shipment < ActiveRecord::Base 
    has_one :invoice, dependent: :restrict 
Problemi correlati