2012-01-11 12 views
8

Tengo envíos y facturas.Rieles 3. validación before_destroy para evitar la eliminación de registros principales

factura pertenece al embarque
embarque tiene una factura

Si el envío tiene una factura, a continuación, el envío no debe ser capaz de ser eliminado. Necesito configurar esto en los modelos porque estoy usando ActiveAdmin.

Así que hice esto en 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 

Pero acabo de recibir un mensaje de color amarillo que dice "El envío no se puede borrar" pero de hecho fue eliminado.

¿Cómo puedo evitar que se elimine el envío?

Respuesta

23

La devolución de llamada before_destroy necesita un valor verdadero/falso para determinar si debe o no proceeed.

Añadir un return false a su check_for_invoice así:

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, sí! Olvidé devolver falso. También publiqué esta parte del código incorrecta 'if invoice.nil?', Se supone que es 'a menos que invoice.nil?' En su lugar. – leonel

+0

Tenía curiosidad sobre la lógica, pero pensé que podría ser algo raro que estuvieras haciendo. Actualizaré mi respuesta para que coincida por el bien de la posteridad. –

+0

Compruebe [esta respuesta a una pregunta similar] (http://stackoverflow.com/a/10257516/703233) para obtener una mejor forma de hacerlo. – nitsas

3

Desde el docs:

Si un before_ * devolución de llamada devuelve falso, todas las devoluciones de llamada más tarde y la acción asociada se cancelan.

Así que trate esto:

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

@Jordan tienes razón en que 'return' no es en su mayoría idiomática en Ruby, pero lo que si la línea no es la última en el método (Además, considere refactorizar)? ¿O qué pasa si luego agrega otras declaraciones en el método y olvida agregar la declaración? Creo que estas son las razones por las que ves 'y return false' en los proyectos de rieles ... – maprihoda

+0

Bien, es un argumento bastante convincente. He retrocedido mi revisión. –

4

Mis 2 centavos en shipment.rb

has_one :invoice, dependent: :restrict 

Creo que va a trabajar, vi esta solución en otro hilo. Estoy probando ahora en mis modelos.

1

para los carriles 4:

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

hará el truco. Si desea una excepción en lugar de un error, use :restrict_with_exception. Ver más en the relevant api docs page.

Para Rails 3 (quizás antes también) Proveedores:

class Shipment < ActiveRecord::Base 
    has_one :invoice, dependent: :restrict 
Cuestiones relacionadas