Tengo algunos modelos que tienen devoluciones de llamada after_save. Por lo general, está bien, pero en algunas situaciones, como al crear datos de desarrollo, quiero guardar los modelos sin que se ejecuten las devoluciones de llamada. ¿Hay una manera simple de hacer eso? Algo parecido a ...
Person#save( :run_callbacks => false )
o
Person#save_without_callbacks
Miré en los documentos de Rails y no encontré nada. Sin embargo, en mi experiencia, los documentos de Rails no siempre cuentan toda la historia.
ACTUALIZAR
Encontré una publicación de blog que explica cómo puedes eliminar las devoluciones de llamada de un modelo como este:
Foo.after_save.clear
No pude encontrar dónde está documentado ese método, pero parece funcionar.
Foo.after_save.clear
eliminaría las devoluciones de llamada para todo el modelo? Y entonces, ¿cómo propones restaurarlos?Respuestas:
Esta solución es solo Rails 2.
Acabo de investigar esto y creo que tengo una solución. Hay dos métodos privados de ActiveRecord que puede usar:
Tendrá que usar enviar para llamar a estos métodos. ejemplos:
Esto es definitivamente algo que realmente solo querrás usar en la consola o al hacer algunas pruebas aleatorias. ¡Espero que esto ayude!
fuente
Use
update_column
(Rails> = v3.1) oupdate_columns
(Rails> = 4.0) para omitir devoluciones de llamadas y validaciones. También con estos métodos,updated_at
se no actualizada.http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_column
# 2: omitiendo las devoluciones de llamada que también funcionan al crear un objeto
fuente
:create_without_callbacks
:( ¿Cómo puedo ejecutar algo similar a eso? (Trabajado en Rails2, eliminado en Rails3).@person
es una variable en un controlador en alguna parte, esta solución significa que las personas que leen su clase de modelo no podrán entender las devoluciones de llamada. Veránafter_create :something_cool
y pensarán "¡genial, algo genial sucede después de crear!". Para comprender realmente su clase de modelo, tendrán que examinar todos sus controladores, buscando todos los pequeños lugares donde ha decidido inyectar lógica. No me gusta> o <;;skip_callback ..., if: :skip_some_callbacks
conafter_create ..., unless: :skip_some_callbacks
para ejecutar esto correctamente con after_create.Actualizado:
La solución de @Vikrant Chaudhary parece mejor:
Mi respuesta original:
ver este enlace: ¿Cómo omitir las devoluciones de llamada de ActiveRecord?
en Rails3,
Supongamos que tenemos una definición de clase:
Enfoque1:
Enfoque2: cuando desee omitirlos en sus archivos rspec o lo que sea, intente esto:
NOTA: una vez hecho esto, si no está en el entorno rspec, debe restablecer las devoluciones de llamada:
funciona bien para mí en rieles 3.0.5
fuente
rieles 3:
fuente
reset_callbacks
no es:after_save
, sino más bien:save
. apidock.com/rails/v3.0.9/ActiveSupport/Callbacks/ClassMethods/…Si el objetivo es simplemente insertar un registro sin devoluciones de llamada o validaciones, y le gustaría hacerlo sin recurrir a gemas adicionales, agregar comprobaciones condicionales, usar SQL RAW o inutilizar su código de salida de alguna manera, considere usar una "sombra" object "apuntando a su tabla db existente. Al igual que:
Esto funciona con todas las versiones de Rails, es seguro para subprocesos y elimina por completo todas las validaciones y devoluciones de llamadas sin modificaciones en su código existente. Simplemente puede incluir esa declaración de clase justo antes de su importación real, y debería estar listo. Solo recuerde usar su nueva clase para insertar el objeto, como:
fuente
Puede intentar algo como esto en su modelo de Persona:
EDITAR: after_save no es un símbolo, pero esa es al menos la milésima vez que he intentado hacerlo uno.
fuente
send
. KOODOSPuedes usar
update_columns
:fuente
La única forma de evitar todas las devoluciones de llamada after_save es hacer que la primera devuelva false.
Quizás podría intentar algo como (no probado):
fuente
Parece que una forma de manejar esto en Rails 2.3 (ya que update_without_callbacks ha desaparecido, etc.), sería usar update_all, que es uno de los métodos que omite las devoluciones de llamadas según la sección 12 de la Guía de validaciones y devoluciones de llamadas de Rails .
Además, tenga en cuenta que si está haciendo algo en su devolución de llamada after_, eso hace un cálculo basado en muchas asociaciones (es decir, una asociación has_many, donde también acepta "atributos_de_temados"), deberá volver a cargar la asociación, en caso de que sea parte del guardado , uno de sus miembros fue eliminado.
fuente
https://gist.github.com/576546
simplemente descargue este parche de mono en config / initializers / skip_callbacks.rb
luego
Project.skip_callbacks { @project.save }
o similar.
todo crédito al autor
fuente
La mayor
up-voted
respuesta puede parecer confusa en algunos casos.Puede usar solo una simple
if
verificación si desea omitir una devolución de llamada, como esta:fuente
Una solución que debería funcionar en todas las versiones de Rails sin el uso de una gema o complemento es simplemente emitir declaraciones de actualización directamente. p.ej
Esto puede (o no) ser una opción dependiendo de cuán compleja sea su actualización. Esto funciona bien para, por ejemplo banderas de actualización de un registro desde dentro de una devolución de llamada after_save (sin retriggering la devolución de llamada).
fuente
#{...}
.fuente
Ninguno de estos puntos al
without_callbacks
complemento que simplemente hace lo que necesita ...http://github.com/cjbottaro/without_callbacks funciona con Rails 2.x
fuente
Escribí un complemento que implementa update_without_callbacks en Rails 3:
http://github.com/dball/skip_activerecord_callbacks
Creo que la solución correcta es reescribir sus modelos para evitar devoluciones de llamada en primer lugar, pero si eso no es práctico a corto plazo, este complemento puede ayudar.
fuente
Si está utilizando Rails 2. Puede usar la consulta SQL para actualizar su columna sin ejecutar devoluciones de llamada y validaciones.
Creo que debería funcionar en cualquier versión de rieles.
fuente
Cuando necesito un control total sobre la devolución de llamada, creo otro atributo que se usa como un interruptor. Simple y efectivo:
Modelo:
Prueba:
fuente
Para crear datos de prueba en Rails, usa este truco:
https://coderwall.com/p/y3yp2q/edit
fuente
Puede usar la gema sneaky-save: https://rubygems.org/gems/sneaky-save .
Tenga en cuenta que esto no puede ayudar a guardar asociaciones sin validaciones. Lanza el error 'created_at no puede ser nulo' ya que inserta directamente la consulta sql a diferencia de un modelo. Para implementar esto, necesitamos actualizar todas las columnas de db generadas automáticamente.
fuente
Necesitaba una solución para Rails 4, así que se me ocurrió esto:
aplicación / modelos / preocupaciones / save_without_callbacks.rb
en cualquier modelo:
entonces tú puedes:
o
fuente
¿Por qué querrías poder hacer esto en desarrollo? Seguramente esto significará que está creando su aplicación con datos no válidos y, como tal, se comportará de manera extraña y no como espera en la producción.
Si desea llenar su base de datos de desarrollo con datos, un mejor enfoque sería construir una tarea de rastrillo que utilizara la gema falsa para crear datos válidos e importarlos a la base de datos creando tantos o pocos registros como desee, pero si es un talón empeñado y tengo una buena razón, supongo que actualizar_sin_callbacks y create_without_callbacks funcionarán bien, pero cuando intentes doblar rieles a tu voluntad, pregúntate a ti mismo que tienes una buena razón y si lo que estás haciendo es realmente una buena idea.
fuente
Una opción es tener un modelo separado para tales manipulaciones, usando la misma tabla:
(El mismo enfoque podría facilitar las cosas para evitar las validaciones)
Stephan
fuente
Otra forma sería usar ganchos de validación en lugar de devoluciones de llamada. Por ejemplo:
De esa forma, puede obtener do_something de forma predeterminada, pero puede anularlo fácilmente con:
fuente
Algo que debería funcionar con todas las versiones
ActiveRecord
sin depender de las opciones o métodos de grabación activos que pueden o no existir.TLDR: use un "modelo de registro activo diferente" sobre la misma tabla
fuente
Para devoluciones de llamada personalizadas, use an
attr_accessor
y anunless
en la devolución de llamada.Defina su modelo de la siguiente manera:
Y luego, si necesita guardar el registro sin presionar las
after_save
devoluciones de llamada que definió, establezca elskip_after_save_callbacks
atributo virtual entrue
.fuente
No es la forma más limpia, pero podría ajustar el código de devolución de llamada en una condición que verifique el entorno de Rails.
fuente