1

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

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造成这种情况?

谢谢!

4

3 回答 3

5

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

Before_save或者after_create更合适。

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

于 2009-08-21T05:20:17.230 回答
1

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

于 2009-08-22T13:02:11.283 回答
0

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

def after_initialize
  return unless self.new_record?
  self.clockin = WorkNote.last_clockout
end
于 2015-07-08T20:23:18.783 回答