How to “update_attributes” without executing “before_save”?

前端 未结 5 767
小蘑菇
小蘑菇 2020-12-15 04:58

I have a before_save in my Message model defined like this:

   class Message < ActiveRecord::Base
     before_save lambda { foo(         


        
相关标签:
5条回答
  • 2020-12-15 05:20

    Use the touch method. It's elegant and does exactly what you want

    0 讨论(0)
  • 2020-12-15 05:23

    update_column or update_columns is the closest method to update_attributes and it avoids callbacks without having to manually circumvent anything.

    0 讨论(0)
  • 2020-12-15 05:24

    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 => ...)
    
    0 讨论(0)
  • 2020-12-15 05:42

    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 .

    0 讨论(0)
  • 2020-12-15 05:42

    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

    0 讨论(0)
提交回复
热议问题