Рельсы 4.2.0 определены? возвращает противоречивые результаты

Rails 4.2.0/Ruby 2.2.1

Я сталкиваюсь с непоследовательным поведением при использовании defined?, чтобы проверить, существует ли класс с заданным именем или нет. Я хочу избежать спасения исключений, используя метод предиката. Но, как видно ниже, он возвращает противоречивые результаты. Такое поведение приводит к сбою некоторого кода, написанного в контроллере.

$ rails c 
Loading development environment (Rails 4.2.0) 
2.2.1 :001 > defined?(User) 
=> "constant" 

2.2.1 :002 > defined?(AuthenticationToken) 
=> nil 

2.2.1 :003 > AuthenticationToken 
=> AuthenticationToken (call 'AuthenticationToken.connection' to establish a connection) 

2.2.1 :004 > defined?(AuthenticationToken) 
=> "constant"

Я также пытался использовать Kernel.const_defined?, но обнаружил такое же непоследовательное поведение.

$ rails c
Loading development environment (Rails 4.2.0)
2.2.1 :001 > Kernel.const_defined?('Role')
 => false 
2.2.1 :002 > Kernel.const_defined?('AuthenticationToken')
 => false 
2.2.1 :003 > AuthenticationToken
 => AuthenticationToken (call 'AuthenticationToken.connection' to establish a connection) 
2.2.1 :004 > Kernel.const_defined?('AuthenticationToken')
 => true 

Есть ли какой-нибудь стандартный способ заставить этот код вести себя последовательно?

Спасибо.


person Jignesh Gohel    schedule 08.12.2015    source источник


Ответы (1)


Основная проблема заключается в том, что в режиме разработки rails загружает код вашего приложения по запросу - эти константы на самом деле не определены.

Это делается с помощью хука const_missing, а const_defined? явно задокументировано как не вызывающее const_missing. На самом деле использование константы вызовет const_missing.

Вы можете попробовать включить config.eager_load, чтобы рельсы загружали весь ваш код при запуске, но это замедлит запуск консоли рельсов, запуск задач и т.д. Я также не уверен, как это сочетается с перезагрузкой кода режима разработки.

person Frederick Cheung    schedule 20.12.2015