2012-07-18 15 views
6

Tengo una aplicación Rails, que usa devoluciones de llamada mucho ... por lo que tengo bastantes funciones llamadas: after_create y: after_commit en varios modelos.¿Cómo organizar complejas devoluciones de llamada en Rails?

Me pregunto si la forma en que lo estoy haciendo ahora es lo mejor.

Básicamente tengo el siguiente escenario:

Class Parent < ActiveRecord::Base 

has_many :children 


after_create :first_function 
after_commit :last_function 

    def first_function 
     if !self.processed? 
      self.children.create(:name => "Richard The Lion Heart") 
      self.processed = true 
      self.save! 
     end 
    end 

    def last_function 
     if self.processed? 
      if !self.processing? 
       self.process 
            self.save! 
       self.processing = true 
       self.save! 
      end 
     end 
    end 

end 

para que pueda ver todo el asunto depende de algunos controles booleanos dual extraña porque de lo contrario second_function se está llamado cada vez que se actualiza el modelo y que puede ser actualizada por la función en sí y por lo tanto la función se llama repetitivamente.

En general, esto me lleva al caso en el que tengo que introducir una nueva verificación booleana para cada devolución de llamada para disparar. Funciona pero no lo veo tan elegante. ¿Qué me estoy perdiendo?

+0

se puede hacer esto before_save? – cpuguy83

Respuesta

6

Debería poder volver a escribir ese código, algo como esto? Por supuesto, su código real probablemente tiene cierta complejidad adicional - TAMBIÉN: este código no ha sido probado.

Class Parent < ActiveRecord::Base 
    has_many :children 

    # only called when a new record is created 
    after_create :first_function 

    # only called for updates, not new records, should still be inside the current transaction 
    after_update :last_function 

    private 
    def first_function 
     self.children.create(:name => "Richard The Lion Heart") 
     # don't call save in here, already in a transaction 
    end 

    def last_function 
     self.process 
     # don't call save in here, already in a transaction   
    end 

    def process 
     # doing stuff .... 
     self.children[0].update_attribute(:name, "Beowulf") 
    end 
end  

http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

Eso es un total de doce devoluciones de llamada, que le da un poder inmenso para reaccionar y prepararse para cada estado del ciclo de vida Active Record. La secuencia para llamar a Base # save para un registro existente es similar, excepto que cada _create callback es reemplazada por la correspondiente _update callback.

uso

p = Parent.new(:foo => "bar") 
p.save 
p.children[0].name 
# => "Richard The Lion Heart" 

p.update_attributes(:baz => "fud") 
p.children[0].name 
# => Beowulf 

ActiveRecord devoluciones de llamada desde la consola carriles (con una p awesome_print)

> ap ActiveRecord::Callbacks::CALLBACKS 
[ 
    [ 0] :after_initialize, 
    [ 1] :after_find, 
    [ 2] :after_touch, 
    [ 3] :before_validation, 
    [ 4] :after_validation, 
    [ 5] :before_save, 
    [ 6] :around_save, 
    [ 7] :after_save, 
    [ 8] :before_create, 
    [ 9] :around_create, 
    [10] :after_create, 
    [11] :before_update, 
    [12] :around_update, 
    [13] :after_update, 
    [14] :before_destroy, 
    [15] :around_destroy, 
    [16] :after_destroy, 
    [17] :after_commit, 
    [18] :after_rollback 
] 
+0

solo para asegurarme de que lo obtengo correctamente. Sugiere usar: after_update over: after_commit b/c: after_update se invoca cuando el registro se acaba de actualizar pero no se guarda, por lo que puede anteceder a: after_commit? – Stpn

+0

Nunca he usado 'after_commit' pero' after_update' se ejecutará durante el guardado de registros existentes; mire el archivo de registro: la actualización posterior estará en la misma transacción de base de datos que el archivo principal; Supongo que 'after_commit' se ejecutará después de que la transacción se haya completado (supongo que es por eso que tuvo que llamar a save yourself) - respuesta actualizada con callbacks – house9

+0

perfecto gracias mucho – Stpn

Cuestiones relacionadas