私は本質的にActiveRecordクエリから返されたレコードを変更するRails 3 gemを構築しています。私がやっていることの1つは、method_missing
とrespond_to?
のメソッドをオーバーライドしていますが、私のrespond_to?
の定義の結果、 "SystemStackError:stack level too deep"エラーが発生する無限ループが発生しているようです。ここでObject.respond_to?無限ループに詰まっています
は、これらの方法の私の元の定義は以下のとおりです。この無限ループが発生した理由を学ぶことを試みることに
def respond_to?(name, *args)
super(name, *args) || parent_association.respond_to?(name)
end
def method_missing(name, *args, &block)
if parent_association.respond_to?(name)
parent_association.send(name, *args, &block)
else
super(name, *args, &block)
end
end
def parent_association
send(parent_association_name) # Essentially yields another ActiveRecord
# instance (e.g.: instance of User), but
# never returns itself.
end
、私はそれが立ち往生だ場所を確認するために、いくつかの「前」と出力「後」とrespond_to?
を再編しました。
before (_run__374051839217347232__initialize__1707831318230746190__callbacks)
after
before (_run__374051839217347232__validation__1707831318230746190__callbacks)
after
before (_run__374051839217347232__validate__1707831318230746190__callbacks)
after
before (_run__374051839217347232__save__1707831318230746190__callbacks)
after
before (_run__374051839217347232__create__1707831318230746190__callbacks)
after
before (created_at)
after
before (created_on)
after
...
しかし、いつでも私がいることを、検索のコールバックを参照してください。
def respond_to?(name, *args)
return true if super(name, *args)
puts "before (#{name})"
result = parent_association.respond_to?(name)
puts "after"
result
end
ランニング
が、予想通り、様々なコールバックとは、それぞれの前と呼び出し後に単一で、実行する方法を属性と思われます無限ループに陥っているように見える:私は私のrespond_to?
をハックした場合
before (_run__374051839217347232__find__1707831318230746190__callbacks)
before (_run__374051839217347232__find__1707831318230746190__callbacks)
before (_run__374051839217347232__find__1707831318230746190__callbacks)
before (_run__374051839217347232__find__1707831318230746190__callbacks)
before (_run__374051839217347232__find__1707831318230746190__callbacks)
before (_run__374051839217347232__find__1707831318230746190__callbacks)
before (_run__374051839217347232__find__1707831318230746190__callbacks)
before (_run__374051839217347232__find__1707831318230746190__callbacks)
...
SystemStackError: stack level too deep
、その後、すべてがスムーズに実行するために表示されます。
def respond_to?(name, *args)
return true if super(name, *args)
return false if name =~ /^_run_.*_find_.*_callbacks$/
parent_association.respond_to?(name)
end
このハッキングが必要なように私は間違っていますか?そして、どうすればそれを避けることができますか?
正確な言葉を使った方がより明確になります。 'parent_association_name'は変数ではなく、' employee'は常に定義されていると思いますが、ロードされていない可能性があります。あなたが実際に "コールバック"を意味するかどうかは不明です。私はあなたが描いていることが、私が言っていたことでもなく、あなたがそれをどのように固定したのかもまだ分かりません。 –