2012-07-18 12 views
6

Mam aplikację Rails, która używa wywołań zwrotnych dużo ... tak, że mam kilka funkcji, które są wywoływane: after_create i: after_commit w wielu modelach.Jak organizować złożone wywołania zwrotne w Railsach?

Zastanawiam się, czy sposób, w jaki teraz to robię, jest najlepszy.

Zasadniczo mam następujący scenariusz:

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 

więc można zobaczyć całość zależy od jakichś dziwnych podwójnych kontroli logicznych bo inaczej second_function jest uzyskiwanie wywoływana za każdym razem model jest aktualizowany i może być aktualizowana przez samą funkcję, więc funkcja jest wywoływana w sposób powtarzalny.

Ogólnie rzecz biorąc prowadzi mnie to do przypadku, w którym muszę wprowadzić nową weryfikację boolowską dla każdego wywołania zwrotnego, aby odpalić. Działa, ale nie uważam tego za elegancki. czego mi brakuje?

+0

Można to zrobić before_save? – cpuguy83

Odpowiedz

6

Powinieneś być w stanie przepisać ten kod - coś takiego? Oczywiście twój prawdziwy kod prawdopodobnie ma jakąś dodatkową złożoność - TAKŻE: ten kod jest nieprzetestowany.

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

To w sumie dwanaście wywołań zwrotnych, które daje ogromną moc do reagowania i przygotowanie się do każdego stanu w cyklu życia usługi Active Record. Sekwencja wywoływania zapisu bazowego # dla istniejącego rekordu jest podobna, z tą różnicą, że każde _backback callback jest zastępowane przez odpowiednie _backdate callback.

Wykorzystanie

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 wywołania zwrotne z konsoli szyn (z awesome_print AP)

> 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

tylko po to, aby upewnić się, że otrzymuję go poprawnie - sugerujesz użycie: after_update przez: after_commit b/c: after_update jest wywoływana, gdy rekord jest właśnie aktualizowany, ale nie zapisany, a więc może poprzedzać: after_commit? – Stpn

+0

Nigdy nie użyłem 'after_commit', ale' after_update' będzie działać podczas zapisywania istniejących rekordów; obejrzyj plik dziennika - następna aktualizacja będzie znajdować się w tej samej transakcji bazy danych, co zapis macierzysty; Zgaduję, że 'after_commit' będzie działał po zakończeniu transakcji (zgadywanie - to dlatego musiałeś zadzwonić, zapisz sam siebie) - zaktualizowana odpowiedź z callbackami – house9

+0

perfect thanks much much – Stpn

Powiązane problemy