Rails:before_save - 堆栈级别太深

Posted

技术标签:

【中文标题】Rails:before_save - 堆栈级别太深【英文标题】:Rails: before_save - Stack level too deep 【发布时间】:2017-09-19 15:16:40 【问题描述】:

我有这个简单的模型:

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

每次创建新的Post 时都会收到Stack level to deep 错误。

现在,当我删除 before_save :re_process, on: :update 时,一切正常。

这条线不应该只在我更新帖子时生效吗?

【问题讨论】:

【参考方案1】:

是的,您在 update 添加的 before_save 运行良好。

问题是你有after_create_commit,代码在记录创建后保存它。

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

所以,基本上,当你创建一个帖子时:

    保存帖子

    调用process回调(after_create_commit)

    调用re_process(因为它在process方法中调用时 做save!)

    再次调用process(因为在re_process中调用)

    等等……

这个循环导致Stack level to deep

希望对您有所帮助!

【讨论】:

3.步骤:到底为什么保存processed 会导致before_save 触发self(帖子)? 不应该before_save 只被self.save! 触发吗? @ariel on: :update or on: :create 在 before_save 上不起作用为此,您必须使用 before_update【参考方案2】:

on: :update or on: :create 不适用于before_save

为此,您必须使用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

如果您将on 选项与before_save 一起使用,则无论on 选项中指定什么,都会执行回调。

希望对你有帮助

【讨论】:

工作,谢谢!这就是我想要完成的:) 很高兴为您提供帮助

以上是关于Rails:before_save - 堆栈级别太深的主要内容,如果未能解决你的问题,请参考以下文章

Rails:before_save 变量内容

Rails - 在 before_save 中获取旧值

Rails :before_save 大写私有方法

带有 MD5 摘要的 Rails 模型 before_save

Ruby on Rails:before_save 字段为小写

我如何在 Rails 3 的控制器中获取 before_save 值?