2012-05-17 655 views
8

Como ya sabe, las devoluciones de llamada before_save se ejecutan antes de before_create devoluciones de llamada.Is: on =>: create valid para una devolución de llamada before_save en Rails 3.2.3

Por lo tanto, algunas personas han sugerido que sería mejor usar before_save :method, :on => :create en lugar de before_create para que el método de devolución de llamada se ejecute en el momento adecuado en relación con otras devoluciones de llamada (como autoguardar devoluciones de llamada). Consulte, por ejemplo, Pivotal Labs blog post y this StackOverflow answer.

Sin embargo, hasta donde puedo decir, la opción :on => :create no logra el efecto deseado en una devolución de llamada before_save. En otras palabras, la devolución de llamada se ejecuta para cada guardado independientemente de si se trata de una creación o no.

La opción :on => :createhace parece ser válido para before_validation devoluciones de llamada, sin embargo.

¿Alguien podría confirmar si se supone que el :on => :create funciona para un before_save? ¿Funcionó en versiones anteriores de Rails y ahora está roto, o los enlaces mencionados anteriormente simplemente se confunden?

Suponiendo que :on => :create no es válido, ¿es aceptable lo siguiente y/o existe una forma mejor?

before_save :callback_method, :if => :new_record? 

Gracias.

+0

me presentó un PR de rieles para agregar un estricto chequeo de argumentos: https://github.com/rails/rails/pull/30919 – seanlinsley

Respuesta

15

Tienes razón, no hay opción :on para la devolución de llamada before_save. Pero, no entiendo, ¿por qué usar before_save en lugar de before_create. before_create se llamará a la devolución de llamada inmediatamente después de before_save.

Por supuesto, puede usar before_save :callback_method, :if => :new_record?. Pero personalmente no me gusta esta solución, ¿qué sucede si necesito agregar condiciones en la opción :if?

Si uno tiene una dependencia entre before_save y before_create devoluciones de llamada, yo sugeriría, para combinar 2 devoluciones de llamada. Por ejemplo (pseudocódigo):

class MyModel < ActiveRecord::Base 
    before_create :prepare_x 
    before_save :do_something_with_x 

    def prepare_x 
    @x = 10 
    end 


    # will not work, because `prepare_x` called after `do_something_with_x` 
    def do_something_with_x 
    @a = 100/@x 
    end 
end 

# || 
# || 
# \/ 

class MyModel < ActiveRecord::Base 

    before_save :do_something_with_x 

    def do_something_with_x 
    @x = 10 if new_record? 
    @a = 100/@x 
    end 
end 
+0

gracias por su respuesta, y en particular para la confirmación that': on =>: create' no es válido. La combinación de devoluciones de llamada suena como una buena idea en el caso general, pero no estoy seguro de que se aplique bien al caso específico de tratar de preparar los datos para una devolución de llamada creada por una asociación de autoguardado, ¿o sí? – Nathan

+1

En relación con su pregunta de por qué quiero usar before_save en lugar de before_create: esto se explica bien en la publicación del blog al que hice referencia. Se está creando una devolución de llamada mediante el código Core Rails a través de una asociación de autoguardado. La devolución de llamada que deseo crear debe ejecutarse antes de la devolución de llamada de autoguardado, y una devolución de llamada before_create ocurriría demasiado tarde. – Nathan

+1

Es una lástima que 'before_save: on =>: create' falle silenciosamente. Sería bueno si funcionaba o arrojaba una excepción. –

Cuestiones relacionadas