Rails table_name_prefix отсутствует - PullRequest
19 голосов
/ 18 января 2012

У меня есть следующая структура каталогов

models/foo/setting.rb
models/foo.rb

foo.rb content

 module Foo
  def self.table_name_prefix
    'foo_'
  end
 end

и setting.rb content

class Foo::Setting < ActiveRecord::Base
end

Как только яя звоню Foo::Setting.find… Я получаю ошибку SQLException: no such table: settings, которая действительно верна, потому что таблица называется foo_settings, поэтому rails, похоже, игнорирует префикс таблицы, указанный для модуля Foo.

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

Ответы [ 4 ]

20 голосов
/ 18 января 2012

Вы определили метод внутри модуля (Foo). Это волшебным образом не определяет этот метод в классе, вложенном в этот модуль.

Я бы попробовал что-то вроде

class Foo < ActiveRecord::Base
  self.abstract_class = true
  self.table_name_prefix = 'foo_'
end

А потом наследовать от Foo

class Foo::Setting < Foo
...
end
7 голосов
/ 09 июня 2015

Вероятно, это связано с загрузчиком рельсов. При этом:

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 поверх каждого файла пространства имен.

Примечание:

Эта ошибка, похоже, была устранена в rails 4. Я много раз использовал второй обходной путь, когда на rails 3, но я пытался воспроизвести ошибку в rails 4, и она больше не отображается. Я думаю, что они изменили способ работы автозагрузчика ... Подробнее см. руководства по рельсам для автозагрузки и перезагрузки констант

1 голос
/ 03 декабря 2013

У меня была такая же проблема.Решил это, изменив либо пространство имен моего приложения, либо модель.

Посмотрите на этот вопрос Использование того же пространства имен для приложения, что и для моделей, приводит к тому, что модели неправильно выбирают родительское пространство имен table_name_prefix.

0 голосов
/ 28 ноября 2016

Просто создайте базовый класс внутри вашего каталога моделей с пространством имен и включите в него 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
...