Ошибка Rails table_name_prefix
У меня есть следующая структура dir
models/foo/setting.rb
models/foo.rb
foo.rb content
module Foo
def self.table_name_prefix
'foo_'
end
end
и content.rb
class Foo::Setting < ActiveRecord::Base
end
Как только я вызываю Foo::Setting.find…
, я получаю сообщение об ошибке SQLException: no such table: settings
, которое действительно правильно, потому что таблица имеет имя foo_settings
, поэтому рельсы, похоже, игнорируют префикс таблицы, указанный для модуля Foo.
Что я могу сделать, чтобы рельсы рассматривали префикс?
Ответы
Ответ 1
Вы определяете метод внутри модуля (Foo). Это не волшебным образом определяет этот метод для класса, вложенного в этот модуль.
Я бы попробовал что-то вроде
class Foo < ActiveRecord::Base
self.abstract_class = true
self.table_name_prefix = 'foo_'
end
И затем наследуем от Foo
class Foo::Setting < Foo
...
end
Ответ 2
Это, вероятно, вызвано автозагрузчиком рельсов. При этом:
module Foo
class Bar
end
end
И затем, пытаясь использовать Foo::Bar
, автозагрузчик сначала попытается найти app/models/foo/bar.rb
. Файл загружен, и module Foo
определяется здесь (хотя и как модуль, содержащий только Bar
), поэтому автозагрузчик никогда не пытается загрузить app/models/foo.rb
.
Это должно произойти только в режиме разработки, так как в режиме производства все ваши файлы require
'd при запуске.
Существует два обходных метода AFAIK:
Обмануть автозагрузчик
объявите свой класс с помощью class Foo::Bar
, чтобы заставить автозагрузчик разрешить постоянный поиск Foo
.
У этого есть раздражающий побочный эффект, что постоянный поиск внутри Bar
НЕ будет находиться внутри Foo
, например:
# app/models/foo.rb
module Foo
BAZ = "baz"
end
# app/models/foo/bar.rb
class Foo::Bar
def baz
BAZ
end
end
здесь Foo::Bar.new.baz
завершится с ошибкой, если вы не указали константу, используя Foo::BAZ
. Это может быть действительно беспорядок при определении ассоциаций ActiveRecord, например.
Требовать модуль
с помощью require_dependency
:
require_dependency 'foo'
module Foo
class Bar
end
end
Это ИМХО - правильное решение, так как оно не нарушает постоянный поиск, но это также немного раздражает, поскольку вам нужно добавить инструкцию require поверх каждого файла с именами.
Примечание:
Эта ошибка, похоже, была решена в рельсах 4. Я часто использовал второй обходной путь на рейках 3, но я попытался воспроизвести ошибку в рельсах 4, и она больше не появляется. Я думаю, они изменили способ работы автозагрузчика... Для получения дополнительной информации см. направляющие направляющих для констант автозагрузки и перезагрузки
Ответ 3
У меня была такая же проблема. Решил его, изменив любое из пространства имен приложений или модели.
Взгляните на question. Использование того же пространства имен для приложения, что и для моделей, приводит к тому, что модели не правильно выбирают родительское пространство имен table_name_prefix.
Ответ 4
Просто создайте базовый класс внутри своего каталога моделей с именами и потребуйте Foo в нем, а затем расширьте свои модели из базового класса.
Скажем, у меня app/models/foo.rb
module Foo
def self.table_name_prefix
'tble_prefix_'
end
end
Тогда в app/models/foo/base_record.rb
require_dependency 'foo'
module Foo
class BaseRecord < ActiveRecord::Base
self.abstract_class = true
end
end
Затем продолжите от BaseRecord
module Foo
class Bar < BaseRecord
end
end