How to "update_attributes" without executing "before_save"?
I have a before_save
in my Message
model defined like this:
class Message < ActiveRecord::Base
before_save lambda { foo(publisher); bar }
end
When I do:
my_message.update_attributes(:created_at => ...)
foo
and bar
are executed.
Sometimes, I would like to update message'开发者_运维技巧s fields without executing foo
and bar
.
How could I update, for example, the created_at
field (in the database) without executing foo
and bar
?
In rails 3.1 you will use update_column.
Otherwise:
In general way, the most elegant way to bypass callbacks is the following:
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
Then, you can do:
Message.skip_callbacks = true # for multiple records
my_message.update_attributes(:created_at => ...)
Message.skip_callbacks = false # reset
Or, just for one record:
my_message.update_attributes(:created_at => ..., :skip_callbacks => true)
If you need it specifically for a Time
attribute, then touch
will do the trick as mentioned by @lucapette .
update_all
won't trigger callbacks
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
Use the touch method. It's elegant and does exactly what you want
You could also make your before_save
action conditional.
So add some field/instance variable, and set it only if you want to skip it, and check that in your method.
E.g.
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
and then somewhere write
my_message.skip_before_save = true
my_message.update_attributes(:created_at => ...)
update_column
or update_columns
is the closest method to update_attributes
and it avoids callbacks without having to manually circumvent anything.
精彩评论