2009-08-27 21 views
65

Mögliche Duplizieren:
How can I avoid running ActiveRecord callbacks?Wie ActiveRecord Rückrufe übersprungen werden?

Ich habe Modell wie dieses

class Vote < ActiveRecord::Base 
    after_save :add_points_to_user 

    ..... 
end 

Ist es möglich, wenn gespeichert, um irgendwie Modell zu zwingen zu überspringen add_points_to_user Aufruf? Möglicherweise etwas wie ActiveRecord#delete vs ActiveRecord#destroy?

+0

Meiner bescheidenen Meinung nach hat die Frage, von der behauptet wird, dass sie bereits eine Antwort hat, nur die Antworten gebrochen. Ich denke also nicht, dass dies ein Duplikat ist. Ich denke, die Antwort, die ich unten gebe, ist der offiziell sanktionierte Ansatz zur Rückruf-Vermeidung. – sheldonh

Antwort

29

Für Rails 2, aber nicht Rails 3 Sie diese verwenden können:

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

leider funktioniert das nicht mehr in Rails 3 :( –

+2

Siehe meine Antwort für einen Hinweis, der Rails 2 und Rails 3 behandelt. – sheldonh

+3

dass 'Model' ist irreführend, das sind Methoden von AR-Instanzen, nicht Klassenmethoden, so' record.send (: (create_without_callbacks) '. – tokland

151

Für Rails 3, ActiveSupport::Callbacks gibt Ihnen die nötige Kontrolle. Ich hatte gerade die gleiche Herausforderung in einem Datenintegrationsszenario, bei dem normalerweise gewünschte Callbacks beiseite geschoben werden mussten. Sie können umsichtig deaktivieren reset_callbacks skip_callback en-masse, oder verwenden Sie, wie folgt aus:

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

..after, die Sie auf Vote Instanzen mit arbeiten: add_points_to_user

gehemmt
+37

Wenn Sie nicht den Rückruf dauerhaft loswerden wollen, aber sagen nur für einen erstellen/speichern dann Sie muss es nach dem Beenden von Callbacks wieder aktivieren: 'User.set_callback: speichern,: nach,: add_points_to_user' Beachten Sie auch, dass, wenn was auch immer Sie zwischen den beiden Aufrufen eine Ausnahme auslösen, Sie es wahrscheinlich wickeln sollten around begin (-rescue) -ensure-block. – Timo

+6

Gibt es ähnliche Funktionen für ein bestimmtes ins Tance? – EyalB

+6

Was ich wahrscheinlich vorschlagen würde ist, setzen Sie 'skip_callback' deklarativ auf die Klasse mit einer': if' Option wie 'if: lambda {@skip_callbacks == true}', und schreiben Sie Methoden, um Fälle dort einzubinden, wo Sie dies tun müssen : 'def some_special_operation !; @skip_callbacks = Wahr; etwas tun; sparen!; @skip_callbacks = false; end 'Könnte eine Context-Manager-Methode verwenden, die den ivar und die Erträge zu einem Block setzt/löscht, aber wenn Sie das sehr oft brauchen, ist wahrscheinlich etwas falsch ;-) ** bearbeiten ** Ugh, ich hasse SO kommentieren Zeilenumbruch Einschränkungen. – ches

41

Die folgenden 2, Schienen Schienen gilt 4 3 und Schienen:

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

es eine Liste von Methoden bereit, die Rückrufe zu überspringen, zu erklären, warum es gefährlich ist, sie ohne sorgfältige Prüfung zu verwenden. Hier abgedruckt unter den Bestimmungen der Creative Commons Namensnennung-Weitergabe unter gleichen Bedingungen 3.0 Lizenz.

12 Skipping Rückrufe

Genau wie bei Validierungen, es ist auch möglich, Rückrufe zu überspringen. Diese Methoden sollten jedoch mit Vorsicht verwendet werden, da wichtige Geschäftsregeln und Anwendungslogik in Rückrufen gespeichert werden können. Umgangen werden, ohne die möglichen Auswirkungen zu verstehen, kann zu ungültigen Daten führen.

  • dekrementieren
  • decrement_counter
  • DELETE_ALL
  • find_by_sql
  • Zuwachs
  • increment_counter
  • Toggle
  • Touch löschen
  • update_column
  • update_all
  • update_counters
+0

Gut zu wissen! und funktioniert gut – Ben

+0

Wie ich weiß, in Rails 4.2, wechseln nur Objekt ändern, aber nicht in der Datenbank gespeichert, müssen Sie speichern Methode nach dem Umschalten aufrufen. Wenn use toggle !, wird es jetzt gespeichert, aber es wird Callback ausgelöst, also sollte es aus dieser Liste entfernt werden. – zw963

+0

@ zw963 Aber toggle! ist nicht auf der Liste, also muss es nicht entfernt werden. Wollen Sie damit sagen, dass ein Non-Bang-Toggle auch Callbacks auslöst und daher entfernt werden muss? Der Rails Guide auf ActiveRecord Callbacks listet immer noch zwischen den Methoden auf, die Callbacks in 4.2.1 überspringen. – sheldonh

28

dies Ihre Validierungen überspringen wird:

vote.save(:validate => false) 

info Weitere here

Um Ihre Rückrufe und Validierungen überspringen, können Sie verwenden, update_column v (3.1) oder update_all

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

Aparentlly funktioniert dies nur mit Activerecord 3.1

Oder:

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

Am Ende haben Sie auch endlich Option i, und dies wird das Everthing überspringen:

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

OK Der letzte ist nicht so hübsch.

+3

Dies überspringt keine Rückrufe, nur die Validierungen – pduersteler

+0

update_all überspringt Rückrufe von http://apidock.com/rails/ActiveRecord/Relation/update_all: "Es instanziiert die beteiligten Modelle nicht und es löst keine Active Record-Rückrufe aus oder Validierungen. " –

+2

update_column funktioniert auch, außer dass die obige Syntax falsch ist. Es erwartet 2 params: vote.update_column (: Betreff, 'CallBacks') –

Verwandte Themen