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

Предотвращение STI при наследовании от модели ActiveRecord

В Rails 3.2.6 у меня есть класс, который наследуется от ActiveRecord:: Base:

class Section < ActiveRecord::Base
  ...
end

Когда я наследую этот класс, Rails предполагает, что я хочу STI:

class AnotherSection < Section
   ..Rails assumes I have a type field, etc...
end

Я хочу унаследовать от класса Section и использовать подкласс как обычный подкласс Ruby без магии Rails STI.

Есть ли способ предотвратить STI при подкласце из модели ActiveRecord::Base?

4b9b3361

Ответ 1

Вы можете добиться этого, отключив inheritance_column для модели, например:

class AnotherSection < Section
  # disable STI
  self.inheritance_column = :_type_disabled

end

Ответ 2

Принятый ответ определенно будет работать, но рекомендуемый (смею сказать "правильный":) способ установить abstract_class:

class Section < ActiveRecord::Base
  self.abstract_class = true
end

Ответ 3

Единственная полностью поддерживаемая стратегия хранения наследования ActiveRecord - это STI. Тем не менее, вы можете имитировать конкретное наследование класса на свой страх и риск. Конкретное наследование класса-таблицы с абстрактным суперклассом отлично работает, как указано smathy.

НО... Если вы хотите сделать AnotherSection просто обычным классом (который не будет сохраняться в базе данных), вы можете отключить столбец дискриминатора (как предложено Veraticus). Однако, если вы сохраните AnotherSection, он будет сохранен в той же таблице, что и раздел, и вы не сможете отличить их друг от друга. Кроме того, если вы используете AnotherSection, чтобы найти раздел, он вернет AnotherSection, нарушив первоначальный экземпляр:

    #create a Section and saves it
    sect = Section.create()
    sect.save() 
    #retrieve the Section as a AnotherSection, breaking polymorphism... 
    sect = AnotherSection.find(sect.id)
    # another section is more than a section, it is inconsistent.

Если AnotherSection не предназначено для сохранения, самый безопасный путь для переопределения операций сохранения, таких как save() и find():

    class AnotherSection < Section
       # disable STI, as pointed by Veraticus
       self.inheritance_column = :_type_disabled
       # disable save and finding
       def save(*args)
         #exception? do nothing?
       end
       def find(*args)
         #exception? do nothing?
       end
       def find_by(*args)
         #exception? do nothing?
       end
       # this does not stops here! there is first, last, and even a forty_two finder method! not to mention associations...
    end

в двух словах, вы можете это сделать, но вы НЕ ДОПУСКАЕТЕ. Риск очень высок. Вы должны рассмотреть другой вариант, например, использовать MIXIN вместо наследования.