Home > Software design >  Update callback running after create via Accepts Nested Attributes - Rails
Update callback running after create via Accepts Nested Attributes - Rails

Time:04-30

When I create a Blog object, both the create and update callbacks are triggered in sequence.

In this case, updating the Blog object deletes all existing images and generates new ones. I want to only generate new images on create, and delete and re-create them on update.

I think it's due to the nested object via accepts_nested_attributes_for, but I can't seem to find a working alternative.

Is this a Rails bug? How can I force the correct callbacks to only trigger once per action?

  class Blog
    has_many :posts
    has_many :images

    accepts_nested_attributes_for :posts

    after_update :destory_existing_images, if: -> { images.any? }
    after_commit :create_images, on: [:update, :create], if: -> { images.none? }

    private

    def destory_existing_images
      images.destroy_all
    end

    def create_screenshots
      images.create!(tag: title)
    end
  end

CodePudding user response:

It would be better if you use separate callbacks. Use after_create_commit for initialization and after_update_commit to update the images.

You could also check if the title changed before you update your images. Dirty API is great for that, your condition then would look like if: -> { images.any? && saved_change_to_title? }.

Solution

  class Blog
    has_many :posts
    has_many :images

    accepts_nested_attributes_for :posts

    after_create_commit :create_images, if: -> { images.none? }
    after_update_commit :update_images, if: -> { images.any? && saved_change_to_title? }

    private
    
    def update_images
      images.destroy_all
      images.create!(tag: title)
    end

    def create_images
      images.create!(tag: title)
    end
  end
  • Related