En essayant d'être DRY, j'essaye d'assigner à la variable d'instance d'un modèle après l'initialisation de l'objet.after_initialize provoque un débordement de pile
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
Cependant, l'appel de méthode en after_initialize
provoque une 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...
Si je commente sur after_initialize
, la méthode last_clockout
n'a pas de problème. Cela ne se produit pas non plus lorsque j'utilise un rappel comme before_save
au lieu de after_initialize
. Pourquoi after_initialize
provoque-t-il cela?
Merci!
Merci pour les réponses utiles! Je comprends ce qu'est le problème. Est-ce que 'default_value_for' n'aurait pas le même problème, cependant? On dirait que tant que la valeur initiale de l'attribut nécessite un find(), un nouvel objet WorkNote devra être instancié et la boucle continuera à se produire. D'autres façons que je peux penser à faire cela: a. affecter la valeur initiale dans le contrôleur, bien que ce ne soit pas là où il appartient b. stocker la valeur par défaut dans un autre modèle, comme Utilisateurs D'autres suggestions? Merci! – rahum
default_value_for fonctionne en remplaçant le getter et en fournissant une valeur par défaut seulement s'il n'en a pas déjà. Il ne modifie pas réellement la valeur dans la base de données ou l'objet sous-jacent. Puisque default_value_for ne s'exécute pas automatiquement lors de la création de l'objet (uniquement lors de l'accès à la colonne), il est impossible de réutiliser une utilisation similaire à la question d'origine. – Luke