Подтвердить что ты не робот

Ошибка 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.

Что я могу сделать, чтобы рельсы рассматривали префикс?

4b9b3361

Ответ 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