Rails: before_save - Stack level too deep

657 views Asked by At

I have this simple model:

class Post < ApplicationRecord

    after_create_commit :process
    before_save :re_process, on: :update

    has_one :processed, class_name: 'Post::Process'

    def process
        self.processed.destroy if self.processed
        processed = self.build_processed
        processed.save!
    end

    private

    def re_process
        self.process if self.title_changed?
    end

end

I get a Stack level to deep error everytime I create a new Post.

Now when I remove before_save :re_process, on: :update everything works fine.

Shouldn't this line take only affect when I am updating a post?

2

There are 2 answers

2
Nimish Gupta On BEST ANSWER

on: :update or on: :create doesn't work for before_save

For this purpose, you have to use before_update

class Post < ApplicationRecord

    after_create_commit :process
    before_update :re_process

    has_one :processed, class_name: 'Post::Process'

    def process
        self.processed.destroy if self.processed
        processed = self.build_processed
        processed.save!
    end

    private

    def re_process
        self.process if self.title_changed?
    end

end

If you are using on option with before_save, the callback will be executed no matter what is specified in on option.

Hope this helps

3
ascherman On

Yes, the before_save you added on update it's working fine.

The problem is that you have the after_create_commit which the code saves the record after it was already created.

def process
  # here the Post was already created
  self.processed.destroy if self.processed
  processed = self.build_processed
  processed.save! # And here, you are updating the Post, so it triggers the re_process
end

So, basically, when you create a Post:

  1. Saves the Post

  2. Calls process callback (after_create_commit)

  3. Calls re_process (because it's called in process method when doing save!)

  4. Calls process again (because it's called in re_process)

  5. And so on...

This loop is causing the Stack level to deep

Hope it helped!