wake-up-neo.com

Wie kann man "update_attributes" ausführen, ohne "before_save" auszuführen?

Ich habe einen before_save in meinem Message Modell wie folgt definiert:

   class Message < ActiveRecord::Base
     before_save lambda { foo(publisher); bar }
   end

Wenn ich mache:

   my_message.update_attributes(:created_at => ...)

foo und bar werden ausgeführt.

Manchmal möchte ich die Felder der Nachricht aktualisieren, ohne foo und bar auszuführen.

Wie kann ich zum Beispiel das Feld created_at (in der Datenbank) aktualisieren, ohne foo und bar auszuführen?

23
Misha Moroshko

In Rails 3.1 verwenden Sie update_column .

Andernfalls:

Im Allgemeinen ist die eleganteste Art, Rückrufe zu umgehen, die folgende:

class Message < ActiveRecord::Base
  cattr_accessor :skip_callbacks
  before_save lambda { foo(publisher); bar }, :unless => :skip_callbacks # let's say you do not want this callback to be triggered when you perform batch operations
end

Dann können Sie Folgendes tun:

Message.skip_callbacks = true # for multiple records
my_message.update_attributes(:created_at => ...)
Message.skip_callbacks = false # reset

Oder nur für einen Datensatz:

my_message.update_attributes(:created_at => ..., :skip_callbacks => true)

Wenn Sie es speziell für ein Time-Attribut benötigen, führt touch den von @lucapette erwähnten Trick aus.

34
jbescoyez

update_all löst keine Rückrufe aus

my_message.update_all(:created_at => ...)
# OR
Message.update_all({:created_at => ...}, {:id => my_message.id})

http://apidock.com/Rails/ActiveRecord/Base/update_all/class

17
fl00r

Verwenden Sie die Methode touch . Es ist elegant und macht genau das, was Sie wollen

6
lucapette

Sie können Ihre before_save-Aktion auch bedingt machen.

Fügen Sie also eine Feld-/Instanzvariable hinzu und setzen Sie sie nur dann, wenn Sie sie überspringen möchten, und überprüfen Sie dies in Ihrer Methode.

Z.B.

before_save :do_foo_and_bar_if_allowed

attr_accessor :skip_before_save

def do_foo_and_bar_if_allowed
  unless @skip_before_save.present?
    foo(publisher)
    bar
  end
end

und dann irgendwo schreiben

my_message.skip_before_save = true
my_message.update_attributes(:created_at => ...)
1
nathanvda

update_column oder update_columns ist die Methode, die update_attributes am nächsten kommt, und vermeidet Rückrufe, ohne etwas manuell umgehen zu müssen.

0
Archonic