Rails: организация моделей во вложенных папках с предупреждением: константа уровня заполнения A, на которую ссылается B:: A
Сегодня я решил реорганизовать большое количество моделей, связанных с пользователем, и у меня возникла проблема с ним.
Раньше у меня была такая структура:
app/models/user.rb
app/models/user_info.rb
app/models/user_file.rb
...
Итак, я переместил все модели user_
в подпапку пользователя следующим образом:
app/models/user.rb
app/models/user/info.rb
app/models/user/file.rb
...
и изменили свои определения на
class User::Info < ActiveRecord::Base
class User::File < ActiveRecord::Base
...
User
модель не была изменена (кроме ассоциаций).
Все работает отлично, кроме модели User::File
. Когда я пытаюсь получить доступ к этой модели, я получаю следующую ошибку:
warning: toplevel constant File referenced by User::File
и действительно, он возвращает стандартный класс файлов Ruby.
Что я делаю неправильно?
UPD1:
root# rails c
Loading development environment (Rails 3.2.13)
2.0.0p195 :001 > User::File
(irb):1: warning: toplevel constant File referenced by User::File
=> File
2.0.0p195 :002 > User::Info
=> User::Info(...)
UPD2:
2.0.0p195 :001 > User::SomeModel
NameError: uninitialized constant User::SomeModel
2.0.0p195 :002 > User::IO
(irb):2: warning: toplevel constant IO referenced by User::IO
=> IO
2.0.0p195 :003 > User::Kernel
(irb):3: warning: toplevel constant Kernel referenced by User::Kernel
=> Kernel
В моем приложении нет классов ввода-вывода или ядра, кроме стандартного ruby.
UPD3:
# app/models/user.rb
class User < ActiveRecord::Base
has_many :files, class_name: 'User::File'
..
end
# app/models/user/file.rb
class User::File < ActiveRecord::Base
belongs_to :user
# some validations, nothing serious
end
Ответы
Ответ 1
Обновление: в этом году рождественский подарок был выпуском Ruby 2.5.0, с которым эта ошибка больше не будет. С Ruby 2.5+ вы получите либо константу, которую вы попросили, либо ошибку. Для более старых версий Ruby читайте:
Ваш класс User::File
не загружен. Вы должны потребовать его (например, в user.rb
).
Следующее происходит, когда ruby /rails видит User::Info
и оценивает его (упрощенный, только User
еще не определен).
- проверить, существует ли
User::Info
- это не (пока)
- проверить, существует ли
Info
- это не (пока)
-
uninitialized constant
→ make reils magic, чтобы найти файл user/info.rb
и потребовать его
- return
User::Info
Теперь давайте снова сделаем это для User::File
- проверить, существует ли
User::File
- это не (пока)
- проверить, существует ли
File
- это (потому что ruby имеет встроенный класс File
)!
- выдать предупреждение, потому что нас попросили
User::File
, но получили ::File
- return
::File
Заметим, что магия рельсов, которая автоматически требует файлов для (пока) неизвестных констант, не работает для User::File
, потому что File
не является неизвестным.
Ответ 2
Попробуйте обратиться к классу как User:: File, чтобы отличить его от обычных рубиновых файлов. Вы можете использовать:: File, чтобы ссылаться на те, когда они неоднозначны