Вопрос

Привет всем, у меня есть кое-что интересное для моего проекта.Мне нужен has_one отношение, в котором это либо один класс, либо другой, но без наследования.Я мог бы обойтись без наследования, если бы это был единственный способ, но две ассоциированные записи содержат совершенно разные данные и вообще не связаны.

То, что мне нужно выяснить, это что-то вроде следующего.

# 1. Foo never belongs to anything.
# 2. Foo MUST have one assigned sub-record for validity.
# 3. Foo can only have either Bar or Baz assigned.
# 4. Bar and Baz have only ONE common property, and aren't
#    related in either data or implementation.

class Foo < ActiveRecord::Base
  # Attributes: id, name, value
  has_one :assignment, :foreign_key => 'assigned_to', :readonly => true
          # Could really use an :object_type for has_one here...
end

class Bar < ActiveRecord::Base
  # Attributes: name,...
end

class Baz < ActiveRecord::Base
  # Attributes: name,...
end

Где Foo имеет одно назначение, типа либо Bar или Baz;у них есть только один общий столбец, так что, возможно, я смогу создать из него родительский объект.Однако, если я заставлю их наследовать от общего объекта (когда данные, которые они содержат, на самом деле являются апельсинами и яблоками), должен ли я создать таблицу для записи?Возможно, мне это сойдет с рук, если запись является абстрактной, а дети - нет?

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

Это было полезно?

Решение

Вы пытаетесь смоделировать что-то, что не соответствует парадигме реляционной базы данных.Все ссылки в SQL имеют одно происхождение и одну цель.

FWIW, Полиморфные ассоциации также являются антишаблоном, потому что они нарушают это правило.Это должно быть признаком того, что это сломанный дизайн, когда Документация говорит, что вы должны отказаться от ограничения ссылочной целостности, чтобы оно заработало!

Вам нужно, чтобы у Foo было два has_one отношения:один - Бару и один - Базе.Затем реализуйте некоторую логику класса, чтобы попытаться гарантировать, что в любом экземпляре Foo заполняется только одна ссылка.То есть из ссылок на Bar и Baz одна должна иметь значение, а другая должна быть равна нулю, но это то, что ваш код должен проверять и применять.

Другие советы

Возможно, один из способов сделать это - создать ассоциации to has-one в Foo для Bar и Baz.Затем создайте метод с именем assignment и assignment=, который может быть единственным способом доступа к Bar и Baz.Вы можете проверить, какой из двух has_ones не равен нулю в методе get, и вернуть этот.В методе присваивания вы можете-проверить, каков тип передаваемой переменной, и установить правильное отношение has-one к этому объекту, а для другого установить значение nil.Это должно охватывать все ваши базы, не будучи слишком сложным.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top