Реализация полиморфных отношений с косвенным столбцом типа / идентификатора - PullRequest
0 голосов
/ 03 мая 2019

У меня есть следующая схема базы данных:

CREATE TABLE public.my_model_foo (
    id bigint NOT NULL,
    foo character varying,
    created_at timestamp without time zone NOT NULL,
    updated_at timestamp without time zone NOT NULL
);

CREATE TABLE public.my_model_bar (
    id bigint NOT NULL,
    bar character varying,
    created_at timestamp without time zone NOT NULL,
    updated_at timestamp without time zone NOT NULL
);

CREATE TABLE public.my_model_indirect (
    id bigint NOT NULL,
    type character varying NOT NULL
);

ALTER TABLE ONLY public.my_model_foo
    ADD CONSTRAINT my_model_foo_pkey PRIMARY KEY (id);

ALTER TABLE ONLY public.my_model_bar
    ADD CONSTRAINT my_model_bar_pkey PRIMARY KEY (id);

ALTER TABLE ONLY public.my_model_indirect
    ADD CONSTRAINT my_model_indirect_pkey PRIMARY KEY (id);

ALTER TABLE ONLY public.my_model_foo
    ADD CONSTRAINT fk_rails_a07be81d64 FOREIGN KEY (id) REFERENCES public.my_model_indirect(id);

ALTER TABLE ONLY public.my_model_bar
    ADD CONSTRAINT fk_rails_157422fcc5 FOREIGN KEY (id) REFERENCES public.my_model_indirect(id);

Таким образом, в основном таблицы my_model_foo и my_model_bar содержат столбцы для моделей MyModel::Foo и MyModel::Bar ActiveRecord, но они берут свой идентификаториз общей таблицы my_model_indirect.Столбец type там будет установлен так же, как Rails ожидает, что он будет настроен для полиморфных отношений, то есть заполнен соответствующим именем модели.

Теперь мой вопрос, учитывая эту схему базы данных,Как мне создать полиморфную связь belongs_to с MyModel::Foo или MyModel::Bar через столбец type в таблице my_model_indirect?Я знаю, что мог бы просто использовать polymorphic: true, если бы столбцы id / type были непосредственно встроены в модель, для которой я устанавливал отношения, но тогда я бы потерял преимущества внешнего ключа, и я не уверен, как настроить ORMчтобы справиться с этим подходом?

Я хотел бы иметь возможность добавить ссылку model_id, которая будет внешним ключом к my_model_indirect.id, и при загрузке модели Rails получитtype из my_model_indirect на основе model_id, а затем получить связанный объект из соответствующей таблицы.

Спасибо

1 Ответ

0 голосов
/ 04 мая 2019

Rails считает, что полиморфные отношения разрешаются двумя полями: id и типом.Когда вы используете polymorphic: true в миграции, создается два поля: тип сохраняется в виде строки, которая ссылается на имя класса и идентификатор, связанный с этой ссылкой.

Мы решаем проблему «own_to» на уровне класса с помощью

belongs_to :fooable, polymorphic: true

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

для миграции

add_reference :my_tables, :fooable, polymorphic: true

родительский объект baz может сделать что-то вроде этого:

class MyModel::Baz < ActiveRecord::Base
   has_one :foo, as: fooable
end

дочерние объекты

class MyModel::Foo < ActiveRecord::Base
  belongs_to :fooable, polymorphic: true
end
...