Как "update_attributes" без выполнения "before_save"?
У меня есть before_save
в моей модели Message
, подобной этой:
class Message < ActiveRecord::Base
before_save lambda { foo(publisher); bar }
end
Когда я это сделаю:
my_message.update_attributes(:created_at => ...)
foo
и bar
.
Иногда я хотел бы обновлять поля сообщений без выполнения foo
и bar
.
Как я могу обновить, например, поле created_at
(в базе данных) без выполнения foo
и bar
?
Ответы
Ответ 1
В rails 3.1 вы будете использовать update_column.
В противном случае:
В общем случае наиболее элегантным способом обхода обратных вызовов является следующее:
class Message < ActiveRecord::Base
cattr_accessor :skip_callbacks
before_save lambda { foo(publisher); bar }, :unless => :skip_callbacks # let say you do not want this callback to be triggered when you perform batch operations
end
Затем вы можете сделать:
Message.skip_callbacks = true # for multiple records
my_message.update_attributes(:created_at => ...)
Message.skip_callbacks = false # reset
Или, только для одной записи:
my_message.update_attributes(:created_at => ..., :skip_callbacks => true)
Если вам это нужно специально для атрибута Time
, тогда touch
выполнит трюк, как указано в @lucapette.
Ответ 2
update_all
не будет вызывать обратные вызовы
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
Ответ 3
Используйте метод touch. Он элегантный и делает именно то, что вы хотите
Ответ 4
Вы также можете сделать действие before_save
условным.
Итак, добавьте переменную field/instance и установите ее только в том случае, если вы хотите пропустить ее, и проверьте это в своем методе.
например.
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
а затем где-нибудь пишите
my_message.skip_before_save = true
my_message.update_attributes(:created_at => ...)
Ответ 5
update_column
или update_columns
является самым близким методом к update_attributes
, и он избегает обратных вызовов без необходимости вручную обойти что-либо.