Как использовать обычные методы ActiveRecord has_many с полиморфными c ассоциациями? - PullRequest
0 голосов
/ 16 марта 2020

Я пытаюсь пересоздать некоторые из моих моделей, чтобы включить полиморфные c ассоциации, но я сталкиваюсь с довольно многими препятствиями.

Даже что-то столь же простое, как Tag.images << @crop_image, возвращает ошибка:

ActiveModel::UnknownAttributeError - unknown attribute 'tag_id' for ImageTag.

Есть ли какие-либо изменения, которые мне нужно внести в метод collection<<, чтобы он правильно использовал столбцы :taggable_id и :taggable_type, которые используются с ассоциация полиморфизма c?

Или есть ошибки в том, как я пытаюсь настроить модели? Rails 5 Way говорит об указании опций source и source_type в моделях, и я попытался реализовать эти рекомендации здесь.

image.rb

has_many :image_tags
has_many :tags, through: :image_tags, source: taggable, source_type: 'Tag'

image_tag.rb

belongs_to :image
belongs_to :taggable, polymorphic: true

def build_taggable(params)
  self.taggable = taggable_type.constantize.new(params)
end

tag.rb

has_many :image_tags
has_many :images, through: :image_tags, source: :taggable, source_type: 'Image'

1 Ответ

0 голосов
/ 17 марта 2020

Aha! Оказывается, я неправильно настраивал ассоциации has_many. Параметр as: :taggable должен быть помещен в таблицу соединений.

Он должен иметь следующий вид:

image.rb

has_many :image_tags, as: :taggable
has_many :tags, through: :image_tags

tag.rb

has_many :image_tags, as: :taggable
has_many :images, through: :image_tags

Возможно, мне еще понадобится указать опции source и source_type позже, но это исправление вернулось в драку!


ОБНОВЛЕНИЕ 20200317:

Хорошо, теперь я чувствую, что теперь понимаю ситуацию немного лучше. Использование полиморфа c со сквозным столом немного теряет свой блеск, потому что каждый из связанных методов должен быть настроен индивидуально. И здесь вступают в игру опции source и source_type.

Итак, с учетом вышеизложенного, если я хочу позволить пользователю звонить image.tags, мне нужно дать модели больше информация, чтобы он знал, что на самом деле означает .tags. Это выглядит примерно так:

has_many :tags, through: :taggable, source_type: 'Tag'

Что все хорошо, но что если пользователь захочет вызвать ВСЕ различные типы теговых таблиц за один раз? 1046 *? На данный момент, я не знаю, возможно ли это. Может быть, вы могли бы «прочитать» уникальные значения, присутствующие в столбце, а затем вызывать их по очереди, как-нибудь?

- ИЛИ! -

Может быть, вы обойдете метод запроса activerecord в целом и просто root через таблицу соединений с SQL запросами? Это может быть лучшим подходом ...

Но сейчас это может быть неуместным ... Единственный способ, которым я знаю, чтобы сделать это в настоящее время, это настроить пользовательские методы запросов для каждого типа. Таким образом, вы получите что-то вроде

has_many :people, through: :taggable, source_type: 'Person'
has_many :businesses, through: :taggable, source_type: 'Business'

И затем вам придется вызывать их по отдельности, а затем объединять в один гигантский массив, похожий на структуру.

...