2010-04-23 7 views
12

Me gustaría agregar un bloque de rescate de inicio a uno de mis controladores para crear una mejor información y construir el mensaje de error correcto para devolver al cliente. ¿El rescate de alguna manera "interrumpe" el proceso de reversión?¿Los raíles realizan una reversión si uso begin ... rescue?

Supongo que los rieles se revierten automáticamente. ¿Cuando sucede? ¿Ya pasó cuando me meto en la cláusula de rescate?

Estoy usando mySQL en Dreamhost y creo que usan innoDB.

+0

favor, eche un vistazo en esta respuesta: http://stackoverflow.com/questions/14329877/render-failing-to-render-correct-template-in-rescue-from- activerecordrollback/35731832 # 35731832 – monteirobrena

Respuesta

0

Simplemente usando begin ... rescue no es suficiente para deshacer una transacción. Es necesario utilizar:

ModelName.transaction do 
end 

Esto se hace de forma explícita en una llamada para salvar, por lo que todas sus devoluciones de llamada se ejecutan juntos. ¿Qué excepciones estás atrapando en tu bloque de rescate? ¿A qué estás respondiendo? ¿Qué tipo de errores?

+0

Estoy recibiendo bloqueos. No creo que tenga suficiente espacio aquí para describirlo. Es para un juego de cartas. Pero en un método de devolución de llamada after_save para mi modelo de PlayerAction, creo otra instancia de PlayerAction. Estoy teniendo problemas con sus modelos relacionados. Cuando eso suceda, quiero deshacer todo, incluido el primer modelo de PlayerAction y sus relaciones que se crearon. Suena como si dijera que los rieles NO hacen transacciones automáticas, ¿verdad? Tengo que iniciarlos explícitamente y desencadenar una reversión? ¿Hay algún recurso en alguna parte para esto? He estado buscando ... – user26270

+0

Lo hace a las transacciones explícitas, pero solo a través de métodos como guardar y atributos_actualizar. Entonces su after_save se ejecutará en la misma transacción. – jonnii

+0

No estoy seguro de qué sugerir sobre puntos muertos, a veces puede volver a ordenar las cosas para evitarlos. Hay algunos complementos para reintentar en interbloqueos (http://github.com/rails/deadlock_retry). Puede valer la pena mirar esos también. – jonnii

14

He estado experimentando con esto. Parece que si su rescate capta la excepción que habría causado la reversión, la parte de la transacción que ya pasó se compromete. En mi caso, quiero que la base de datos vuelva a la forma en que estaba antes de que comenzara la transacción, pero aún quiero manejar la excepción.

terminé con esto:

self.transaction do 
    first_operation 
    begin 
    operation_that_might_violate_db_constraint 
    rescue ActiveRecord::RecordNotUnique 
     #deal with the error 
     raise ActiveRecord::Rollback #force a rollback 
    end 
end 

La parte raise ActiveRecord::Rollback se asegura de que la transacción se deshace por completo. Sin él, los cambios de first_operation terminarían comprometiéndose.

El ActiveRecord :: Rollback es un tipo especial de excepción que no supera el nivel de la transacción, por lo que no terminará con una excepción no detectada que representa la página de error.

No estoy seguro de que esta sea la manera estándar de hacer esto, pero parece que funciona.

+0

tenga en cuenta que si detecta la excepción dentro del bloque de transacción y desea hacer algo en el rescate como enviar un correo electrónico, fallará debido a la transacción que lo impide. –

-2

También puede probar mi respuesta para la restitución, la captura y la representación para el método de crear usando ActiveRecord :: Base.transaction: - Click Here

Gracias

-1

Rollback no serán procesadas.

ejemplo:

create_table "helps", :force => true do |t| 
    t.string "title",       :null => false 
    t.text  "content" 
end 

#Rails console 
Help.transaction do 
    Help.create! title: "aaa" 
    begin 
    Help.create! content: "111" 
    rescue 
    p "create error." 
    end 
    Help.create! title: "bbb" 
end 

#get this 
>> "create error." 
Help.count 
>> 2 
Cuestiones relacionadas