Обновить атрибут таблицы сопоставления в ассоциации «Многие ко многим»

#ruby-on-rails

#ruby-on-rails

Вопрос:

У меня настроена ассоциация «многие ко многим» в Rails с ActiveRecord. Допустим, таблицы являются

  ------------                  ----------------                  ---------- 
| categories | -- has many -= | category_items | =- has many -- | products | 
 ------------                  ----------------                  ---------- 
  

В таблице category_items у меня есть стандартный набор идентификаторов плюс дополнительный атрибут под названием «тип»:

 id:int 
category_id:int
product_id:int
category_type:string
  

К счастью, Rails предоставляет несколько отличных помощников для упрощения назначения в таблице сопоставления. Например:

 p = Product.first   # p.id => 1
c = Category.first  # c.id => 1

# now to make the assignment

p.categories << c
# or
p.categories.create(c)
  

Это все хорошо, но, допустим, я хочу автоматически обновить поле «тип» именем класса другой таблицы. Итак, для приведенных выше примеров моя строка category_items будет выглядеть следующим образом:

 id = 1 (or some number)
category_id = 1 
product_id = 1
category_type = nil
  

Но я бы хотел, чтобы category_type равнялся «Продукту». Есть ли у меня способ создать обратный вызов или определить что-то в ассоциации, что автоматически установило бы поле category_type? Я знаю, что в полиморфных ассоциациях вы можете использовать что-то вроде:source или:as, чтобы сделать что-то подобное, но полиморфные ассоциации в ассоциациях «многие ко многим» выдают ошибку.

Есть идеи?

Спасибо!

Комментарии:

1. Продукт может иметь более одной категории?

2. да, продукт может иметь более одной категории.

Ответ №1:

Вы пробовали полиморфный метод для category_items, подобный этому:

 class CategoryItem < ActiveRecord::Base
  belongs_to :category, :polymorphic => true
  belongs_to :product
end

class ACategory < ActiveRecord::Base
  has_many :category_items, :as => :category
end

class AnotherCategory < ActiveRecord::Base
  has_many :category_items, :as => :category
end

class Product < ActiveRecord::Base
  has_many :category_items
end
  

Я думаю, это поможет!

Комментарии:

1. Я не верю, что это сработает. Выдает ошибку HasManyThroughAssociationPolymorphicError при попытке добавить записи. Существует плагин has_many_polymorphs, который, я полагаю, будет работать, но я хотел бы найти решение без плагина, если это возможно.

2. Реальный вопрос, который у меня возникает, заключается в том, как автоматически добавить класс, который я пытаюсь присоединить к категории, в таблицу category_items.

Ответ №2:

В итоге я создал отдельные методы получения / установки. В вашем случае методы в продукте:

установщик

 def set_category_type(category_id, type) 
  category_items = self.category_items.select { |category_item| category_item.category_id == category_id}
  if category_items.length > 0
    category_item = category_items.first
    category_item.type = type
    category_item.save
  else
    CategoryItem.create(:product_id => self.id, :category_id => category_id, :type => type)
  end
end
  

средство получения

 def category_type(category_id)
  category_item = self.category_items.where(:category_id => category_id ).first()
  if category_item.nil?
    nil # or some other default type value
  else
    category_item.type
  end
end
  

В принципе, это было то, что мне было нужно, но я не смог найти более элегантного способа. Пожалуйста, покажите мне лучший способ, если вы знаете.