尝试DRY,我试图在对象初始化后分配给模型的实例变量。
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
会导致这种情况?
谢谢!
答案 0 :(得分:5)
每当对象被实例化(new'ed)时调用initialize。你在self.last_clockout中的find调用是创建一个对象,然后以递归方式调用after_initialize。因此无限递归和堆栈溢出。
Before_save
或after_create
更合适。
请参阅http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
答案 1 :(得分:1)
我发现default_value_for是一种非常好的方法。
答案 2 :(得分:0)
另一种方法是检查初始化对象是否是新的,例如:
def after_initialize
return unless self.new_record?
self.clockin = WorkNote.last_clockout
end