Я строю камень Rails 3, который существенно изменяет записи, возвращаемые из запроса ActiveRecord. Одна из вещей, которые я делаю, - переопределить методы method_missing
и respond_to?
, но, похоже, мое определение respond_to?
приводит к бесконечному циклу, который вызывает ошибку «SystemStackError: уровень стека слишком глубокий».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?
с некоторыми «до» и «после» выхода, чтобы увидеть, где он застрял ,
def respond_to?(name, *args)
return true if super(name, *args)
puts "before (#{name})"
result = parent_association.respond_to?(name)
puts "after"
result
end
При работе, кажется, что различные обратные вызовы и приписывать методы работают, как и ожидалось, с одним до и после вызова для каждого:
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
...
Однако, в любое время я вижу найти обратный вызов, что кажется, чтобы быть пойманным в бесконечном цикле:
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
Если я взломать мой respond_to?
, то все выглядит гладко:
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' всегда определен, хотя он может и не быть загружен. Не уверен, что вы действительно имеете в виду «обратный вызов». Я все еще не уверен, как то, что вы описываете, не то, что я говорил, и то, как вы его исправили. –