似乎有多种方法可以处理多外键关联。我处理这个问题的每一种方式都有其缺点,因为我是 Rails 的新手,我相信其他人也遇到过类似的情况,我可能正在研究很久以前解决的问题。
我的问题是:
处理多索引键关联的有效方法是什么,同时仍保留所有其他 Rails sql 修饰符(例如 :include 等)?
我的场景是:
我有一个表关联如下(简化),用于通过链接将人们与其他人联系起来:
People
+----+-----------+
| id | name |
+----+-----------+
| 1 | Joe |
+----+-----------+
| 2 | Sally |
+----+-----------+
| 3 | Bob |
+----+-----------+
Links
+----+-----------+---------+
| id | origin_id | rcvd_id |
+----+-----------+---------+
| 1 | 2 | 1 |
+----+-----------+---------+
| 2 | 1 | 3 |
+----+-----------+---------+
| 3 | 3 | 2 |
+----+-----------+---------+
从上面链接表的第 1 行,可以看到一个人(Sally = 2)链接到另一个人(Joe = 1)。
如果我的外键是“origin_id”,我很容易找到所有人员链接。但这只会显示发起链接的人。在我的场景中,我需要查看所有链接,无论它们是由个人发起还是接收的。例如,如果我要询问 Sally 的所有链接(Sally = 2),我想要的结果是:
Links
+----+-----------+---------+
| id | origin_id | rcvd_id |
+----+-----------+---------+
| 1 | 2 | 1 |
+----+-----------+---------+
| 3 | 3 | 2 |
+----+-----------+---------+
因此我有 2 个索引键,“origin_id”和“rcvd_id”。
可以解决的一种方法是使用方法:
class Person < ActiveRecord::Base
has_many :link_origins, :class_name => "Link", :foreign_key => :origin_id, :dependent => :destroy
has_many :link_rcvds, :class_name => "Link", :foreign_key => :rcvd_id, :dependent => :destroy
def links
origin_person + rcvd_person
end
然而,这效率不高。例如,这需要从数据库中收集整个集合,然后才能使用 paginate 方法(我正在使用 will_paginate gem),因为 paginate 应该通过限制调用的记录数来加速该过程。整个收集完成后不限制记录。
此外,上面不允许我调用例如 Joe.links(:first).origin_id.name。不完全是这段代码,但意味着我无法在所选链接的 origin_id 上调用 Person 详细信息,因为 links 方法不知道 origin_id 与 People 表相关。
到目前为止,最可行的解决方案似乎是 :finder_sql。
class Person < ActiveRecord::Base
has_many :links, :finder_sql => 'SELECT * FROM links WHERE (links.origin_id = #{id} or links.rcvd_id = #{id})'
这给出了 Person_id 匹配 Links.origin_id 或 Links.rcvd_id 的所有链接。
此选项的缺点是使用 :finder_sql 排除了自 Rails 以来的所有其他 sql 修饰符
不知道如何解析和修改您提供的 SQL。例如,我将无法将 :include 选项与 :finder_sql 一起使用。
所以,现在我正在使用 :finder_sql, 解决方案。但似乎以不需要 :finder_sql 的方式完成此关联可能还有一段距离。例如,有没有办法在保留 Active Record 提供的 Rails sql 修饰符的同时编写自定义 sql 字符串。
对以上有什么想法吗?
最佳答案
我确实找到了解决方案,但结果证明我可能问错了问题。我没有发现有多个索引键,因为我没有实现一些自定义 sql 来破坏不同的 Rails 助手。
我想我的问题仍然存在,但我如何解决这个问题是从不同的角度看待问题。我刚刚创建了关联,因为它们是:
belongs_to :rcvd_person, :class_name => 'Person', :foreign_key => :rcvd_id
belongs_to :origin_person, :class_name => 'Person', :foreign_key => :origin_id
和一个自定义的 sql 语句:
class Person...
has_many :links, :finder_sql => 'SELECT * FROM links WHERE origin_id = #{id} OR rcvd_id = #{id}'
end
然后我就可以在我的视野中以我想要的方式操纵记录。如果其他人正在做类似的事情,我做了:
<% person.links.each do |link| %>
<% if link.origin_id == person.id %>
<%= link.rcvd_person.given_name %>
<% else %>
<%= link.origin_person.given_name %>
<% end %>
<% end %>
关于ruby-on-rails - Rails - 多索引键关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3421873/