2009-08-21 157 views
1

嘗試成爲DRY,我試圖在對象初始化後分配給模型的實例變量。after_initialize導致堆棧溢出

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造成這種情況?

謝謝!

回答

1

我發現default_value_for是這樣做的一個很好的辦法。

+0

謝謝你的幫助的答覆!我得到了什麼問題。雖然'default_value_for'不會有同樣的問題嗎?似乎只要屬性的初始值需要find(),新的WorkNote對象將不得不被實例化,並且循環將繼續發生。 我可以這樣想的其他方式: a。在控制器中分配初始值,儘管這不是它所屬的區域 b。將默認值存儲在另一個模型中,如用戶 有沒有其他建議?謝謝! – rahum 2009-08-24 17:25:19

+0

default_value_for通過重寫getter並僅在缺少值時才提供缺省值來工作。它實際上並沒有改變數據庫或底層對象的值。由於default_value_for在創建對象時不會自動運行(僅當訪問該列時),因此無法像原始問題那樣使用這種方法進行遞歸。 – Luke 2009-08-25 00:04:45

0

另一種方法是,以檢查是否初始化的對象是新的或沒有,例如:

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