2015-07-31 2 views
2

У меня есть модель Image, которая has_many. Версия также является изображением, устанавливающим как самореферентное отношение.Поиск потомков в самореференциальных отношениях в Rails

class Image < ActiveRecord::Base 
    belongs_to :parent, class_name: 'Image' 
    has_many :versions, class_name: 'Image', foreign_key: :parent_id 
end 

Когда новый образ создается обратный вызов ищет дб для образа, который имеет такое же имя. Если он найдет один, он установит свой parent_id на идентификатор нового изображения. Это создает дерево, структура:

| id | name | parent_id | 
-------------------------- 
| 1 | a.gif |   2 | 
| 2 | a.gif |   3 | 
| 3 | a.gif |  NULL | 
-------------------------- 

Есть ли простой способ получить все потомки изображения? image.versions находит изображение с id 2, как и ожидалось. Для того, чтобы получить изображение с идентификатором 1 я должен пройти через изображение 2.

image = Image.find(3) 
versions = image.versions # this finds image 2 
descendents = versions.each { |v| v.versions } # etc... 

Я попытался с has_one соотношением:

belongs_to :parent, class_name: 'Image' 
    has_one :version, class_name: 'Image', foreign_key: :parent_id 
    has_many :versions, through: :version 

Это еще только получает изображение с идентификатором 2, а не целое дерево спуски. У меня есть два известных варианта:

  1. Используйте обратный вызов для обновления всех изображений с тем же именем, но я бы предпочел не использовать более сложные обратные вызовы.
  2. Используйте отдельную таблицу для хранения версий. Но это сложно по двум причинам.
    1. Поскольку я отслеживаю всю активность на изображении, преобразовывая изображение в ImageVersion, его ссылки будут потеряны в таблице Activity (это изменит класс и идентификатор).
    2. Люди создают несколько новых изображений одновременно (они не обновляются один за другим), и только после того, как они вставлены, я могу сделать управление версиями, что является дорогостоящим процессом. Это означает, что по умолчанию будут созданы новые изображения. Преобразование их в версии и обновление оригинала оказывается очень сложным из-за механики загрузок.
+1

Я бы не сделал это самооценкой, а имел класс «Image» и «ImageVersion». Это сделает логику намного проще, а также отслеживание дедов. Тогда 'Image' будет иметь много': image_versions', и вы могли бы управлять отношениями в этой таблице. В настоящее время технически изображение 2 является единственной другой версией изображения 3, потому что изображение 1 представляет собой версию изображения 2, которая в данный момент больше похожа на родословную. – engineersmnky

+1

Я думаю, что у вас неправильное назначение parent_id. Если вы делаете a.gif id с идентификатором 1, то вы его пересматриваете, а текущее изображение не имеет каких-либо предыдущих ревизий, тогда вы создадите новое изображение с parent_id = 1, тогда ваши следующие изменения могут посмотреть, он имеет parent_id и будет соответствовать ему. Чтобы повторить, исходный файл не должен иметь parent_id. ревизии должны иметь parent_id.Любая ревизия пересмотра будет иметь parent_id предыдущей ревизии. –

+0

@engineersmnky, что моя моя первоначальная идея, но я не могу создать отдельную модель, потому что у меня есть модель Activity, которая отслеживает все, что происходит на изображении. Преобразуя Image в ImageVersion, я должен найти всю активность, принадлежащую старому изображению, и сделать ссылку на ImageVersion. Это возможно, поскольку Activity является полиморфным, но более сложным, чем это решение. –

ответ

0

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

Это упростит ситуацию, и это будет (на мой взгляд) лучший подход.

Но если вам действительно нужно, чтобы сделать это, вы должны проверить этот драгоценный камень, я никогда не использовал его, но это, кажется, именно то, что вы просите: https://github.com/take-five/activerecord-hierarchical_query

Надеется, что это помогает.

+0

Смотрите мои комментарии по моему вопросу. Я не могу этого сделать, потому что я отслеживаю активность. –

+1

Тогда, может быть, этот драгоценный камень может помочь вам запросить вашу базу данных –