Многоуровневое has_many, через has_and_belongs_to_many - PullRequest
1 голос
/ 11 марта 2020

Я пытаюсь создать трехуровневое отношение в Rails, которое выглядит примерно так:

+---------+      +---------+
| Brand 1 |      | Brand 2 |
++------+-+      +---+---+-+
 |      `------------|---|-------------.
 |                   |   `-----------. |
+v-----------+    +--v---------+    +v-v---------+
| Category 1 |    | Category 2 |    | Category 3 |
++------+----+    +--+-+-------+    +----------+-+
 |      |            | |                       |
 |      `----------. | `-------------.         `---------.
+v-----------+    +v-v---------+    +v-----------+    +--v---------+
| Template 1 |    | Template 2 |    | Template 3 |    | Template 4 |
+------------+    +------------+    +------------+    +------------+

Обратите внимание, что Template 2 является членом как Category 1, так и Category 2, и что каждая из этих категорий относится к разным брендам. Также обратите внимание, что Category 3 является общим для двух брендов.

В настоящее время отношения определяются следующим образом.

class Brand < ApplicationRecord
  has_many :categories
  has_many :templates, through: :categories
end

class Category < ApplicationRecord
  belongs_to :brand
  has_and_belongs_to_many :templates
end

class Template < ApplicationRecord
  has_and_belongs_to_many :categories
  has_many :brands, through: :categories
end

Я не могу обновить отношение Brand-Template, поэтому шаблон не «фильтруется» по бренду, потому что категории являются общими. В настоящее время я получаю эту ошибку.

ActiveRecord :: HasManyThroughNestedAssociationsAreReadonly at / templates / 7 Невозможно изменить ассоциацию «Template # бренды», поскольку она проходит через несколько других ассоциаций.

Как я могу изменить отношение Brand-Template, чтобы решить эту проблему?

1 Ответ

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

Я изменил Brand-Template на has_and_belongs_to_many. Теперь я могу просто написать область действия на Template примерно так:

scope :by_brand, ->(id) { joins(:brands).where(brands: { id: id }) }

Это делает мой запрос немного громоздким, но работает. Это заставляет меня задуматься, есть ли более эффективный запрос.

...