after_initialize导致堆栈溢出

发布于 2024-08-02 16:36:47 字数 2557 浏览 4 评论 0原文

为了保持干燥,我试图在对象初始化后分配给模型的实例变量。

class WorkNote < ActiveRecord::Base

  def after_initialize
    self[:clockin]= WorkNote.last_clockout
  end

  def self.last_clockout
    WorkNote.find(:first, :order => "clockout DESC").clockout
  end
end

但是,after_initialize中的方法调用会导致SystemStackError

ActiveRecord::StatementInvalid: SystemStackError: stack level too deep: SELECT * FROM "work_notes"  ORDER BY clockout DESC LIMIT 1
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/connection_adapters/abstract_adapter.rb:212:in `log'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/connection_adapters/sqlite_adapter.rb:157:in `execute'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/connection_adapters/sqlite_adapter.rb:402:in `catch_schema_changes'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/connection_adapters/sqlite_adapter.rb:157:in `execute'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/connection_adapters/sqlite_adapter.rb:305:in `select'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/connection_adapters/abstract/database_statements.rb:7:in `select_all_without_query_cache'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/connection_adapters/abstract/query_cache.rb:62:in `select_all'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:661:in `find_by_sql'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:1553:in `find_every'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:1510:in `find_initial'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:613:in `find'
    from /Users/noob/jobs/app/models/work_note.rb:10:in `last_clockout'
    from /Users/noob/jobs/app/models/work_note.rb:6:in `after_initialize'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/callbacks.rb:347:in `send'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/callbacks.rb:347:in `callback'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:1662:in `send'
... 5116 levels...

如果我注释掉after_initialize,则last_clockout方法没有问题。当我使用像 before_save 这样的回调而不是 after_initialize 时,也不会发生这种情况。为什么 after_initialize 会导致这种情况?

谢谢!

Attempting to be DRY, I'm trying to assign to a model's instance variable after object initialization.

class WorkNote < ActiveRecord::Base

  def after_initialize
    self[:clockin]= WorkNote.last_clockout
  end

  def self.last_clockout
    WorkNote.find(:first, :order => "clockout DESC").clockout
  end
end

However, the method call in after_initialize causes a SystemStackError:

ActiveRecord::StatementInvalid: SystemStackError: stack level too deep: SELECT * FROM "work_notes"  ORDER BY clockout DESC LIMIT 1
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/connection_adapters/abstract_adapter.rb:212:in `log'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/connection_adapters/sqlite_adapter.rb:157:in `execute'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/connection_adapters/sqlite_adapter.rb:402:in `catch_schema_changes'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/connection_adapters/sqlite_adapter.rb:157:in `execute'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/connection_adapters/sqlite_adapter.rb:305:in `select'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/connection_adapters/abstract/database_statements.rb:7:in `select_all_without_query_cache'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/connection_adapters/abstract/query_cache.rb:62:in `select_all'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:661:in `find_by_sql'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:1553:in `find_every'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:1510:in `find_initial'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:613:in `find'
    from /Users/noob/jobs/app/models/work_note.rb:10:in `last_clockout'
    from /Users/noob/jobs/app/models/work_note.rb:6:in `after_initialize'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/callbacks.rb:347:in `send'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/callbacks.rb:347:in `callback'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:1662:in `send'
... 5116 levels...

If I comment out after_initialize, the last_clockout method has no problems. Neither does this happen when I use a callback like before_save instead of after_initialize. Why is after_initialize causing this?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小伙你站住 2024-08-09 16:36:47

每当实例化(新建)对象时都会调用初始化后。 self.last_clockout 中的 find 调用正在创建一个对象,然后递归调用 after_initialize。因此,无限递归和堆栈溢出。

Before_saveafter_create 更合适。

请参阅http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

After initialize is called whenever an object is instantiated (new'ed). Your find call in self.last_clockout is creating an object, and then recursively calling the after_initialize. Hence the infinite recursion and stack overflow.

Before_save or after_create are more appropriate.

See http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

被翻牌 2024-08-09 16:36:47

我发现 default_value_for 是一个非常好的方法这样做的。

I've found default_value_for is a very good way of doing this.

墨落成白 2024-08-09 16:36:47

另一种方法是检查初始化的对象是否是新的,例如:

def after_initialize
  return unless self.new_record?
  self.clockin = WorkNote.last_clockout
end

Another approach would be to check if the initialized object is new or not, e.g.:

def after_initialize
  return unless self.new_record?
  self.clockin = WorkNote.last_clockout
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文