Полиморфные модели взлома - PullRequest
3 голосов
/ 12 мая 2010

Несмотря на то, что я знаю, что, по крайней мере, насколько мне известно, это не стандартный способ создания ассоциаций с ActiveRecord, я ищу помощь для реализации "гибернатской" полиморфной модели.

Например, рассмотрим следующую базовую модель:

# Content only has one property named path
class Content < ActiveRecord::Base
  self.abstract_class = true
end

И содержание бетона:

# Audio only has one property on it's own (duration).
# However, it should also inherit Content's property (path)
class Audio < Content
end

Теперь при использовании ActiveRecord происходит нечто относительно интересное, точнее Rails 3 beta 3 ActiveRecord. Если вы установили abstract_class на false в модели содержимого и выполняете следующее:

Audio.create!(:path => '/dev/null')

Это вроде работает с точки зрения Hibernate. То есть запись контента создается с идентификатором 1, а аудиозапись также создается с идентификатором = 1.

Однако проблема # 1 заключается в том, что для того, чтобы это сработало, вам, очевидно, необходимо отключить абстрактный класс, что в некоторой степени нарушает весь смысл этого примера абстрактного содержимого.

Кроме того, проблема # 2 заключается в том, что если вы включите abstract_class, вы потеряете свойства содержимого при создании экземпляров Audio. И, если вы отключите его, вы потеряете свойства Audio при создании экземпляра Audio.

В идеале , когда сталкивается с абстрактным классом, который затем разделяется на подклассы, ActiveRecord предоставляет абстрактные + конкретные свойства конкретному классу, который создается, в данном случае Audio. Фактически, при создании экземпляра Audio у нас будет:

audio = Audio.new #=> <Audio id: nil, duration: nil, path: nil, created_at: nil, updated_at: nil> 

И затем [естественно], когда вы назначаете audio.path = '/ dev / null' и выполняете операцию сохранения, ActiveRecord будет знать, что атрибут пути унаследован, поэтому его необходимо сохранить на уровне родительского класса. Кроме того, при той же операции сохранения, если вы установите ненаследуемое свойство аудио, ActiveRecord также сохранит эти изменения в таблице аудиозаписей.

Мой вопрос после этого вступления: как можно обойти активную запись и улучшить ее таким образом?

По сути, давайте предположим, что мы разрабатываем драгоценный камень, который призван обеспечить активную запись с такого рода функциональностью. Как бы вы пошли и сделать это?

PS: На самом деле я думаю о разработке такого драгоценного камня, хотя такая хакерская атака не должна пройти без предварительного обдумывания. Итак, ваши отзывы приветствуются.

С уважением, DBA

1 Ответ

2 голосов
/ 05 ноября 2010

Я понимаю, что вы собираетесь здесь, но, к сожалению, я не думаю, что вы можете заставить это работать из коробки так, как вы хотите.

В основном ActiveRecord использует наследование модели для двух вещей:

  • Абстрактные классы, от которых подклассы могут наследовать код и поведение, но НЕ структуру таблицы. Вы можете реализовать атрибут #path в Content, используя attr_accessor, и он будет наследоваться подклассами, но он будет не сохраняться в базе данных, если таблица для вашего подкласса модели не имеет 'path Колонка.

  • Наследование отдельных таблиц, где подклассы наследуют оба поведение и устойчивость таблиц.

Вы можете смешать их, но не существует сценария, когда модель ActiveRecord может наследовать постоянный столбец из абстрактного класса. Всегда есть соответствие 1: 1 между постоянными атрибутами и столбцами таблицы.

...