10

Si hago lo siguiente:¿Cómo after_save trabajo al guardar un objeto

@user.name = "John"  
@user.url = "www.john.com" 
@user.save 

Si uso after_save

@user.url = "www.johnseena.com" 
@user.save 

¿Qué pasará cuando hago esto?

Creo que debería guardar el valor debido a la devolución de llamada 'after_save'.

+0

¿Realmente está usando la variable de instancia '@ user' en la devolución de llamada' after_save'? – Samiron

+2

Realmente tiene que trabajar para explicar lo que necesita un poco mejor y dar algunos ejemplos más de lo que ha intentado. – simonmorley

Respuesta

27

En mi opinión, si llama a la función save en una devolución de llamada after_save, se bloqueará en una recursión a menos que ponga un guardia al principio. como esto

class User < AR::Base 
     after_save :change_url 

     def change_url 
      #Check some condition to skip saving 
      url = "www.johnseena.com" 
      save    #<======= this save will fire the after_save again 
     end 
end 

Sin embargo, aparte de poner un guardia, se puede utilizar también update_column

def change_url 
    update_column(:url, "www.johnseena.com") 
end 

En este caso, no se disparará after_save. Sin embargo, disparará after_update. Así que si usted tiene cualquier operación de actualización en esa llamada en ese entonces usted está en la repetición de nuevo :)

+0

Una gran manera de explicar Gracias por su tiempo. – SSP

+1

NOTA: '# update_column' en realidad [omite las devoluciones de llamada] (http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_columns). – jibiel

4

Si modifica algo en el after_save, no se guardará, ya que el save ya se ha realizado. La única posibilidad de intervenir es revertir toda la transacción. Si agrega otro save en el after_save, entonces será un bucle infinito.

6

El after_save devolución de llamada se activará independientemente de su un ahorro o una actualizaciónen ese objeto.

También,

update_column no desencadena ningún devoluciones de llamada (es decir after_update) y salta validaciones también. ver http://apidock.com/rails/ActiveRecord/Persistence/update_column

U debe utilizar específicamente after_create o after_update dependiendo de la operación y su temporización.

after_create :send_mail 
def send_x_mail 
    #some mail that user has been created 
end 

after_update :send_y_mail 
def send_y_mail 
    #some data has been updated 
end 

after_save :update_some_date 
def update_some_data 
    ... 
    action which doesnt update the current object else will trigger the call_back 
end 

Véase también What is the difference between `after_create` and `after_save` and when to use which? y devoluciones de llamada para ver http://ar.rubyonrails.org/classes/ActiveRecord/Callbacks.html#M000059

+0

'after_update' y' before_update' existen a partir de los rieles 4.1. Puede consultar la lista completa de devoluciones de llamada disponibles desde [Guía de Rails] (http://guides.rubyonrails.org/active_record_callbacks.html#available-callbacks) –

1

En lugar de realizar dos consultas a la base de datos y preocuparse por la recursividad, es posible que desee considerar simplemente la modificación de la carga útil de datos antes de que entre al servidor.

class User < AR::Base 
     before_save :change_url 

     def change_url 
      url = "www.johnseena.com" 
     end 
end 
0

Muchas gracias a todos los que me han ayudado aquí. Aquí está la solución que resolvió mi problema. Modifiqué por modelo de orden a lo siguiente:

class Order < ActiveRecord::Base 

    has_and_belongs_to_many :users 

    validates :item, presence: true 

    def add_order(username, order) 
    user = User.where(username: username).first 
    if !user.nil? 
     user.orders.create(item: order.item) 
    end 
    end 

    def remove_order(order) 
    end 

end 
Cuestiones relacionadas