Rails 多态关联(遗留数据库)

发布于 2024-08-16 12:32:54 字数 1515 浏览 5 评论 0原文

我使用的是旧数据库,因此我对数据模型没有任何控制权。他们使用了很多多态链接/连接表,就像这样

create table person(per_ident, name, ...)

create table person_links(per_ident, obj_name, obj_r_ident)

create table report(rep_ident, name, ...)

,其中 obj_name 是表名,而 obj_r_ident 是标识符。 因此,链接报告将按如下方式插入:

insert into person(1, ...)
insert into report(1, ...)
insert into report(2, ...)

insert into person_links(1, 'REPORT', 1)
insert into person_links(1, 'REPORT', 2)

然后人员 1 将有 2 个链接报告,1 和 2。

我可以理解拥有这样的数据模型可能带来的好处,但我主要看到一个很大的缺点:使用约束不可能确保数据正直。但可惜的是,我无法再改变这一点了。

但是为了在 Rails 中使用它,我正在研究多态关联,但没有找到解决这个问题的好方法(因为我无法更改列名称,并且没有轻易找到方法来做到这一点)。

不过我确实想出了一个解决方案。请提供建议。

class Person < ActiveRecord::Base

  set_primary_key "per_ident"
  set_table_name "person"
  has_and_belongs_to_many :reports,
                         :join_table => "person_links",
                         :foreign_key => "per_ident",
                         :association_foreign_key => "obj_r_ident",
                         :conditions => "OBJ_NAME='REPORT'"
end

class Report < ActiveRecord::Base

  set_primary_key "rep_ident"
  set_table_name "report"
  has_and_belongs_to_many :persons,
                     :join_table => "person_links",
                     :foreign_key => "obj_r_ident",
                     :association_foreign_key => "per_ident",
                     :conditions => "OBJ_NAME='REPORT'"
end

这是可行的,但我想知道是否有更好的解决方案,使用多态关联。

I am using a legacy database, so i do not have any control over the datamodel. They use a lot of polymorphic link/join-tables, like this

create table person(per_ident, name, ...)

create table person_links(per_ident, obj_name, obj_r_ident)

create table report(rep_ident, name, ...)

where obj_name is the table-name, and obj_r_ident is the identifier.
So linked reports would be inserted as follows:

insert into person(1, ...)
insert into report(1, ...)
insert into report(2, ...)

insert into person_links(1, 'REPORT', 1)
insert into person_links(1, 'REPORT', 2)

And then person 1 would have 2 linked reports, 1 and 2.

I can understand possible benefits having a datamodel like this, but i mostly see one big shortcoming: using constraints is not possible to ensure data integrity. But alas, i cannot change this anymore.

But to use this in Rails, i was looking at polymorphic associations but did not find a nice way to solve this (since i cannot change the columns-names, and did not readily find a way to do that).

I did come up with a solution though. Please provide suggestions.

class Person < ActiveRecord::Base

  set_primary_key "per_ident"
  set_table_name "person"
  has_and_belongs_to_many :reports,
                         :join_table => "person_links",
                         :foreign_key => "per_ident",
                         :association_foreign_key => "obj_r_ident",
                         :conditions => "OBJ_NAME='REPORT'"
end

class Report < ActiveRecord::Base

  set_primary_key "rep_ident"
  set_table_name "report"
  has_and_belongs_to_many :persons,
                     :join_table => "person_links",
                     :foreign_key => "obj_r_ident",
                     :association_foreign_key => "per_ident",
                     :conditions => "OBJ_NAME='REPORT'"
end

This works, but i wonder if there would be a better solution, using polymorphic associations.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一花一树开 2024-08-23 12:32:54

至少从Rails 4.2.1开始,您可以将foreign_type传递给belongs_to声明,以指定用于多态关联的“类型”的列的名称

http://apidock.com/rails/v4.2.1/ActiveRecord/Associations/ClassMethods/belongs_to

At least as of Rails 4.2.1, you can pass foreign_type to a belongs_to declaration to specify the name of the column to be used for the 'type' of the polymorphic association

http://apidock.com/rails/v4.2.1/ActiveRecord/Associations/ClassMethods/belongs_to

岁月静好 2024-08-23 12:32:54

当然,您可以覆盖列名称,但是快速扫描 Rails API 并没有显示任何地方可以覆盖多态“类型”列。因此,您无法将其设置为“obj_name”。

它很难看,但我认为您的表中的每种类型的对象都需要一个 HABTM。

也许能够做这样的事情:

{:report => 'REPORT'}.each do |sym, text|
  has_and_belongs_to_many sym,
    :join_table => "person_links",
    :foreign_key => "obj_r_ident",
    :association_foreign_key => "per_ident",
    :conditions => "OBJ_NAME='#{text}'"
end

至少这样所有常见的东西都会保留DRY,您可以轻松添加更多关系。

You can override the column names, sure, but a quick scan of the Rails API didn't show me anywhere to override the polymorphic 'type' column. So, you wouldn't be able to set that to 'obj_name'.

It's ugly, but I think you'll need a HABTM for each type of object in your table.

You might be able to do something like this:

{:report => 'REPORT'}.each do |sym, text|
  has_and_belongs_to_many sym,
    :join_table => "person_links",
    :foreign_key => "obj_r_ident",
    :association_foreign_key => "per_ident",
    :conditions => "OBJ_NAME='#{text}'"
end

At least that way all the common stuff stays DRY and you can easily add more relationships.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文