使用间接type / id列实现多态关系

时间:2019-05-03 16:39:58

标签: ruby-on-rails orm rails-activerecord

我具有以下数据库架构:

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_foomy_model_bar表包含MyModel::FooMyModel::Bar ActiveRecord模型的列,但是它们从共享表{{1}中获取其ID }。此处的my_model_indirect列的设置方式与Rails期望为多态关系设置的方式相同,即以适当的模型名称填充。

我的问题是,现在,鉴于此数据库架构,我将如何通过typebelongs_toMyModel::Foo建立多态MyModel::Bar关系type表中的列?我知道,如果id / type列直接嵌入到要设置其关系的模型中,那么我可以使用my_model_indirect,但是这样我将失去外键优势,并且不确定如何设置ORM可以处理这种方法吗?

我想做的是能够添加一个polymorphic: true引用,该引用将成为model_id的外键,并且在加载模型时,Rails会获取{{1}从my_model_indirect.idtype,然后从相应的表中检索关联的对象。

谢谢

1 个答案:

答案 0 :(得分:0)

Rails认为多态关系由两个字段(一个id和一个类型)解析。在迁移中使用polymorphic: true时,它将创建两个字段,该类型保存为字符串,该字符串引用了类名和与该引用关联的ID。

我们使用

解决了课程级别的“ belongs_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