How to determine if a record is just created or updated in after_save

后端 未结 8 1180
失恋的感觉
失恋的感觉 2020-12-23 08:44

The #new_record? function determines if a record has been saved. But it is always false in the after_save hook. Is there a way to determine whether the record i

相关标签:
8条回答
  • 2020-12-23 09:20

    For Rails 4 (checked on 4.2.11.1) results of changes and previous_changes methods are empty hashes {} on object creation inside after_save. So attribute_changed? methods like id_changed? won't work as expected.

    But you can take advantage of this knowledge and - knowing that at least 1 attribute has to be in changes on update - check if changes is empty. Once you confirm that it's empty, you must be during object creation:

    after_save do
      if changes.empty?
        # code appropriate for object creation goes here ...
      end
    end
    
    0 讨论(0)
  • 2020-12-23 09:26

    No rails magic here that I know of, you'll have to do it yourself. You could clean this up using a virtual attribute...

    In your model class:

    def before_save
      @was_a_new_record = new_record?
      return true
    end
    
    def after_save
      if @was_a_new_record
        ...
      end
    end
    
    0 讨论(0)
  • 2020-12-23 09:29

    I was looking to use this for an after_save callback.

    A simpler solution is to use id_changed? (since it won't change on update) or even created_at_changed? if timestamp columns are present.

    Update: As @mitsy points out, if this check is needed outside of callbacks then use id_previously_changed?. See docs.

    0 讨论(0)
  • 2020-12-23 09:29

    Since the object has already been saved, you would you need to look at the previous changes. The ID should only change after a create.

    # true if this is a new record
    @object.previous_changes[:id].any?
    

    There is also an instance variable @new_record_before_save. You can access that by doing the following:

    # true if this is a new record
    @object.instance_variable_get(:@new_record_before_save)
    

    Both are pretty ugly, but they would allow you to know whether the object has been newly created. Hope that helps!

    0 讨论(0)
  • 2020-12-23 09:31

    There is an after_create callback which is only called if the record is a new record, after it is saved. There is also an after_update callback for use if this was an existing record which was changed and saved. The after_save callback is called in both cases, after either after_create or after_update is called.

    Use after_create if you need something to happen once after a new record has been saved.

    More info here: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

    0 讨论(0)
  • 2020-12-23 09:40

    I like to be specific even I aware that :id shouldn't change in normal, but

    (byebug) id_change.first.nil?
    true
    

    It always cheaper to be specific instead finding very weird unexpected bug.

    The same way if I expect true flag from untrustworthy argument

    def foo?(flag)
      flag == true
    end
    

    This saves a lot of hours to not sitting on weird bugs.

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