Несмотря на то, что это решено, я просто хотел сообщить об этом и сообщить, как я исправил эту проблему. У меня были те же симптомы, что и у OP, первоначальный запрос .id() работал нормально, последующие запросы .id() выдавали сообщение об ошибке «слишком глубокий стек». Это странная ошибка, поскольку обычно она означает, что у вас где-то есть бесконечный цикл. Я исправил это, изменив:
config.action_controller.perform_caching = true
config.cache_classes = false
to
config.action_controller.perform_caching = true
config.cache_classes = true
в средах/production.rb.
ОБНОВЛЕНИЕ: основной причиной этой проблемы оказался файл cache_store. MemoryStore по умолчанию не сохраняет модели ActiveRecord. Это довольно старая ошибка, и довольно серьезная, я не уверен, почему она не была исправлена. В любом случае, обходным путем является использование другого cache_store. Попробуйте использовать это в вашем config/environments/development.rb:
config.cache_store = :file_store
ОБНОВЛЕНИЕ № 2: К. Бедард опубликовал этот анализ проблемы. Кажется, это красиво.
Сам столкнувшись с этой проблемой (и неоднократно застряв на ней), я исследовал ошибку (и, надеюсь, нашел хорошее решение). Вот что я знаю об этом: Это происходит, когда ActiveRecord::Base#reset_subclasses вызывается диспетчером между запросами (только в режиме разработки).
ActiveRecord::Base#reset_subclasses стирает хэш inheritable_attributes (где хранится #skip_time_zone_conversion_for_attributes). Это произойдет не только с объектами, сохраняемыми через запросы, как показывает «приложение для тестирования обезьян» из № 1290, но и при попытке доступа к сгенерированным методам ассоциации в AR, даже для объектов, которые живут только по текущему запросу.
Эта ошибка была вызвана этой фиксацией, где объявление #skip_time_zone_conversion_for_attributes было изменено с base.cattr_accessor в base.class_inheritable_accessor. Но опять же, тот же самый коммит исправил еще кое-что. Первоначально представленный здесь патч, который просто избегает очистки instance_variables и instance_methods в reset_subclasses, действительно приводит к массивным утечкам, и суммы утечек кажутся прямо пропорциональными сложности приложения (то есть количеству моделей, ассоциаций и атрибутов в каждой из них). У меня есть довольно сложное приложение, которое пропускает почти 1 МБ при каждом запросе в режиме разработки, когда применяется патч. Так что это нежизнеспособно (для меня во всяком случае).
Пытаясь решить эту проблему разными способами, я исправил первоначальную ошибку (skip_time_zone_conversion_for_attributes был равен нулю во втором запросе), но обнаружил еще одну ошибку (которой просто не произошло, потому что первое исключение было бы возбуждено до того, как добраться до него). Похоже, что об этой ошибке сообщается в # 774 (переполнение стека в method_missing для метода 'id').
Теперь, что касается решения, мой патч (прилагается) делает следующее: он добавляет методы-оболочки для методов #skip_time_zone_conversion_for_attributes, гарантируя, что он всегда читает/записывает значение как class_inheritable_attribute. Таким образом, ноль больше никогда не возвращается.
Это гарантирует, что метод id не будет стерт при вызове reset_subclasses. AR немного странный в этом, потому что он сначала определяет его непосредственно в исходном коде, но переопределяет себя с помощью #define_read_method при первом вызове. И именно это приводит к сбою после перезагрузки (поскольку reset_subclasses затем стирает его).
Я также добавил тест в reload_models_test.rb, который вызывает reset_subclasses, чтобы попытаться имитировать перезагрузку между запросами в режиме разработки. На данный момент я не могу сказать, действительно ли он запускает механизм перезагрузки, как это происходит в цикле запросов диспетчера в реальном времени. Я также проверил со скрипта/сервера, и ошибка исчезла.
Извините за длинную вставку, это отстой, что проект маяка рельсов является частным. Патч, упомянутый выше, является частным.
person
Cory
schedule
26.05.2011