2009-08-27 11 views
65

Powiel możliwe:
How can I avoid running ActiveRecord callbacks?Jak pominąć oddzwonienia ActiveRecord?

Mam modelu jak ten

class Vote < ActiveRecord::Base 
    after_save :add_points_to_user 

    ..... 
end 

Czy można jakoś wymusić modelu aby pominąć wywołanie add_points_to_user gdy zbawiony? Prawdopodobnie coś w rodzaju ActiveRecord#delete vs ActiveRecord#destroy?

+0

Moim skromnym zdaniem, pytanie, na które ma się już odpowiedzieć, ma tylko zepsute odpowiedzi. Więc nie sądzę, że to kwalifikuje się jako duplikat. Myślę, że odpowiedź, którą przedstawię poniżej, to oficjalnie usankcjonowane podejście do redukcji zwrotów. – sheldonh

Odpowiedz

29

Dla szyn 2, ale nie szyny 3 można z nich korzystać:

object.send(:create_without_callbacks) 
object.send(:update_without_callbacks) 
+7

Niestety to już nie działa w Rails 3 :( –

+2

Zobacz moją odpowiedź na porady dotyczące Rails 2 i Rails 3. – sheldonh

+3

, że 'Model' jest wprowadzający w błąd, są to metody instancji AR, a nie metody klas, więc' record.send (: create_without_callbacks) '. – tokland

151

dla szyn 3, ActiveSupport::Callbacks daje niezbędną kontrolę. Właśnie miałem do czynienia z tym samym wyzwaniem w scenariuszu integracji danych, w którym normalnie pożądane-wywołania zwrotne musiały zostać odsunięte na bok. Można reset_callbacks en-masse, lub użyć skip_callback wyłączyć rozważnie, tak:

Vote.skip_callback(:save, :after, :add_points_to_user) 

..after który można obsługiwać w instancjach głosu z: add_points_to_user hamował

+37

Jeśli nie chcesz na stałe pozbyć się callbacku, ale powiedz tylko, aby utworzyć/zapisać, to będzie musiał włączyć go ponownie po twoich pominiętych callbackach: 'User.set_callback: save,: after,: add_points_to_user' Zauważ, że jeśli to, co robisz pomiędzy 2 wywołaniami, może spowodować wyjątek, powinieneś go zawinąć około początku (-rescue) -zabezpieczenia-bloku – Timo

+6

Czy istnieje podobna funkcjonalność dla określonych ins Tancerz? – EyalB

+6

To, co pewnie bym zasugerował, ustawia deklaratywnie na klasie klasę 'skip_callback' z opcją': if' taką jak 'if: lambda {@skip_callbacks == true}' i zapisuje metody, aby zawijać przypadki, w których musisz to zrobić : 'def some_special_operation !; @skip_callbacks = true; Zrób coś; zapisać!; @skip_callbacks = false; koniec "Mógłby użyć metody menedżera kontekstu, która ustawia/rozbraja ivar i daje blok, ale jeśli potrzebujesz tego dużo, prawdopodobnie coś jest nie tak ;-) ** edytuj ** Ugh, nienawidzę ograniczeń linii komentarza. – ches

41

stosuje następujące do szyn 2, szyny 3 i szyny 4:

http://guides.rubyonrails.org/v3.2.13/active_record_validations_callbacks.html#skipping-callbacks

zapewnia listę metod, które pominąć wywołania zwrotne, wyjaśniając dlaczego jest to niebezpieczne z nich korzystać bez starannego rozważenia. Przedrukowane tutaj zgodnie z postanowieniami licencji Creative Commons Attribution-Share Alike 3.0.

12 Pomijanie oddzwaniania

Podobnie jak w przypadku walidacji, możliwe jest również, aby pominąć wywołania zwrotne. Te metody powinny być używane ostrożnie, ponieważ ważne reguły biznesowe i logika aplikacji mogą być przechowywane w callbackach. Pomijanie ich bez zrozumienia potencjalnych konsekwencji może spowodować, że doprowadzi do nieprawidłowych danych.

  • zmniejszyć
  • decrement_counter
  • usuwać
  • delete_all
  • find_by_sql
  • przyrost
  • increment_counter
  • przełącznik
  • dotykowy
  • update_column
  • update_all
  • update_counters
+0

Dobrze wiedzieć! i działa dobrze – Ben

+0

Jak wiem, w Railsach 4.2, przełącznik tylko zmienić obiekt, Ale nie zapisane w bazie danych, musisz wywołać metodę zapisu po przełączeniu. jeśli użyjesz przełącznika !, to jest teraz zapisywane, ale wywoła ono oddzwanianie, więc powinno zostać usunięte z tej listy. – zw963

+0

@ zw963 Ale przełącz! nie znajduje się na liście, więc nie trzeba go usuwać. Czy mówisz, że przełącznik inny niż bang uruchamia również wywołania zwrotne, a więc trzeba go usunąć? Poradnik Rails na Callbackach ActiveRecord wciąż wymienia przełączniki pomiędzy metodami, które pomijają wywołania zwrotne w 4.2.1. – sheldonh

28

Pozwoli to pominąć swoje walidacji:

vote.save(:validate => false) 

więcej informacji here

Aby omijając swoje wywołania zwrotne i walidacji, można użyć, update_column v (3.1) lub update_all

vote = Vote.first 
vote.update_column(:subject, 'CallBacks') 

Aparentlly działa to tylko z ActiveRecord 3.1

Lub:

Vote.where('id = ?', YourID).update_all(:subject => 'CallBacks') 

W końcu trzeba też wreszcie opcję i to pominie Everthing:

execute "UPDATE votes SET subject = 'CallBacks' WHERE id = YourID" 

OK ten ostatni nie jest taki ładny.

+3

to nie pomija wywołań zwrotnych, tylko sprawdzanie poprawności – pduersteler

+0

update_all pomija wywołania zwrotne z http://apidock.com/rails/ActiveRecord/Relation/update_all: "Nie tworzy instancji zaangażowanych modeli i nie wyzwala wywołań zwrotnych Active Record lub zatwierdzenia. " –

+2

update_column działa również, ale powyższa składnia jest niepoprawna. Oczekuje 2 params: vote.update_column (: subject, "CallBacks") –