Как завершить двустороннюю полиморфную связь has_many: through в Rails 3 (без has_many_polymorphs или других плагинов)?

Я знаю, что к этой теме уже несколько раз подходили по-разному, но мне не удалось синтезировать другие вопросы, чтобы соответствовать этому конкретному варианту использования Rails 3:

Я пытаюсь построить модель данных, в которой есть вложения и вложения. Любое вложение может быть связано с присоединяемым и наоборот. Я бы хотел, чтобы это в конечном итоге использовалось как комбинация плагинаcts_as (plays_as_attachable и actions_as_attachment).

Моя текущая схема использует модель Attacher с двумя полиморфными отношениями own_to, чтобы попытаться выполнить это.

Конкретный случай, описанный здесь, включает в себя присоединяемую модель (хорошо) и две модели прикрепления (изображение и фильм).

Вот что у меня есть на данный момент:

attacher.rb

class Attacher < ActiveRecord::Base
    belongs_to :attachment, :polymorphic => true
    belongs_to :attachable, :polymorphic => true
end

good.rb

class Good < ActiveRecord::Base
    has_many :attachment_relations, :as => :attachable, :class_name => 'Attacher'
    has_many :attached_images, :through => :attachment_relations, :source => :attachment, :source_type  => 'Image'
    has_many :attached_movies, :through => :attachment_relations, :source => :attachment, :source_type  => 'Movie'
end

image.rb

class Image < ActiveRecord::Base
    has_many :attachable_relations, :as => :attachment, :class_name => 'Attacher'
end

movie.rb

class Movie < ActiveRecord::Base
    has_many :attachable_relations, :as => :attachment, :class_name => 'Attacher'
end

Это работает постольку, поскольку я могу делать следующее:

@g = Good.create!
@i = Image.create!
@m = Movie.create!

@g.attached_images << @i
@g.attached_images       # [#<Image id: 1 ... >]

@g.attached_movies << @m
@g.attached_movies       # [#<Movie id: 1 ... >]

@g.attachment_relations  # [#<Attacher id: 1, attachable_id: 1, attachable_type: "Good", attachment_id: 1, attachment_type: "Image" ...>, #<Attacher id: 2, attachable_id: 1, attachable_type: "Good", attachment_id: 1, attachment_type: "Movie" ...>]

Суть моего вопроса заключается в следующем: могу ли я использовать ассоциации для создания следующего метода / возврата, чтобы я мог делать такие вещи, как @g.attachments.where( ... ):

@g.attachments           # [#<Image id: 1 ... >, #<Movie id: 1 ... >]

Я пробовал кучу таких вещей:

good.rb

class Good < ActiveRecord::Base
    has_many :attachment_relations, :as => :attachable, :class_name => 'Attacher'
    has_many :attachments, :through => :attachment_relations
end

Но они, как правило, бросают мне вот это:

ActiveRecord::HasManyThroughAssociationPolymorphicError: Cannot have a has_many :through association 'Good#attachments' on the polymorphic object 'Attachment#attachment'

Думаю, мне в принципе нужно что-то, что могло бы действовать как source_type => :any ...

Кроме того, это мой первый вопрос по StackOverflow, поэтому, пожалуйста, дайте мне знать, если я могу что-то сделать, чтобы улучшить свой вопрос. Заранее спасибо! :)


person jrh    schedule 24.04.2011    source источник


Ответы (2)


К сожалению, я пришел к выводу, что нет простого или стандартного способа сделать это. Самым ясным базовым решением, которое я нашел, является ответ Squeegy на этот вопрос: Rails полиморфны многие ко многим Association, где он ссылается на довольно простой модуль has_relations.

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

person jrh    schedule 18.06.2011

к сожалению, это действительно невозможно с рельсами, вы можете попытать счастья с помощью этого расширения: https://github.com/kronn/has_many_polymorphs/tree/

Вы должны быть готовы к работе, просто добавив эту строку в свой Gemfile:

gem 'kronn-has_many_polymorphs'

и запустив эту команду в папке приложения rails:

bundle
person Schmurfy    schedule 16.06.2011
comment
Спасибо @Schmurfy. Похоже, вы правы в том, что это невозможно без взлома нового кода. Я бы принял ваш ответ, за исключением того, что вопрос конкретно требует решения, которое не использует has_many_polymorphs, поэтому я думаю, что последующий ответ, который я предоставил, более подходит для людей, которые могут наткнуться на этот вопрос в будущем. - person jrh; 18.06.2011