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

Rails STI - Предотвращение базового класса от экземпляра

Есть ли какой-либо путь в ситуации Rails Rails, чтобы вызывать ошибку, когда базовый класс инициализирован? Переопределение инициализации будет выполняться, но затем оно будет передано в подклассы.

Спасибо

4b9b3361

Ответ 1

Ответ Джона Топли на самом деле ошибочен. Установка abstract_class= true в базовом классе фактически приведет к тому, что дочерние классы перестанут автоматически устанавливать свой тип. Кроме того, если вы не задаете имя_таблицы в базовом классе, дочерние классы будут жаловаться, что их таблица не существует.

Это связано с тем, что целью abstract_class= true является настройка наследования, когда вы НЕ используете STI, и хотите иметь абстрактный класс (класс, не поддерживаемый таблицей db) в иерархии классов между ActiveRecord:: Base и один или несколько классов моделей.

Инициализация рейза - одно решение, также добавление validates_presence_of: type в базовый класс является решением.

Обратите внимание, что если вы переопределите инициализацию, вам нужно вызвать super:

def initialize(*args)
  raise "Cannot directly instantiate an AbstractUser" if self.class == AbstractUser
  super
end

Ответ 2

Вы можете попробовать следующее:

class BaseClass
  def initialize
    raise "BaseClass cannot be initialized" if self.class == BaseClass
  end
end

class ChildClass
end

результат будет:

a = BaseClass.new  # Runtime Error
b = ChildClass.new # Ok

Надеюсь, что поможет

Ответ 3

В функции initialize проверьте, что класс является базовым классом STI.

Хотя вопрос в том, почему вы хотели бы это сделать? Кажется более вероятным, что попробовать другой дизайн может помочь вам больше.

Ответ 4

Я часто предпочитаю просто использовать метод класса new private:

class Base
  private_class_method :new 
end

Таким образом, случайное создание класса Base вызывает ошибку, но все же возможно создать экземпляр с помощью Base.send(:new) для записи тестов для базового класса.

Ответ 5

Вы можете сделать self.abstract_class = true в базовом классе, чтобы сообщить ActiveRecord, что это абстрактный класс.