有几种处理多个外键关联的方法。每种方法都有其缺点,由于我是Rails的新手,我相信其他人也遇到了类似的情况,并且可能已经解决了很久以前的问题。
我的问题是:
如何有效地处理多个索引键关联,同时仍保留所有其他Rails SQL修饰符(例如:include等)?
我的情景是:
我有一个表格关联,如下所示(简化),用于通过链接将人与其他人连接起来:
从上面的链接表的第一行可以看出,一个人(Sally = 2)与另一个人(Joe = 1)相连。
如果我的外键是“origin_id”,那么我很容易找到一个人的所有链接。但这只会显示起始于一个人的链接。在我的场景中,我需要查看所有链接,无论它们是由一个人发起还是接收。例如,如果我要求查看Sally的所有链接(Sally = 2),我想要的结果将是:
因此,我有两个索引键,分别是“origin_id”和“rcvd_id”。
解决这个问题的一种方法是使用一个方法:
然而,这并不高效。例如,这需要从数据库中收集整个集合,然后才能使用 paginate 方法(我正在使用 will_paginate gem),这与其限制调用的记录数以加快进程的速度背道而驰。而是在整个集合完成之后再限制记录。
此外,上面的代码将不允许我调用例如 Joe.links(:first).origin_id.name 这样的代码。虽然不完全是这段代码的意思,但我的意思是,我无法调用所选链接的 origin_id 上的 Person 详细信息,因为 links 方法不知道 origin_id 与 People 表相关联。
到目前为止,最可行的解决方案似乎是使用 :finder_sql。
这将给出所有链接,其中Person_id与Links.origin_id或Links.rcvd_id匹配。
这种方法的缺点是,使用:finder_sql会排除所有其他sql修饰符,因为Rails不知道如何解析和修改提供的SQL。例如,我将无法在:finder_sql中使用:include选项。
所以,现在我正在使用:finder_sql解决方案。但似乎有一种方法可以完成此关联,而无需使用:finder_sql。例如,是否有一种方法编写自定义sql字符串,同时保留Active Record提供的Rails sql修饰符。
对以上内容有什么想法吗?
我的问题是:
如何有效地处理多个索引键关联,同时仍保留所有其他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 |
+----+-----------+---------+
从上面的链接表的第一行可以看出,一个人(Sally = 2)与另一个人(Joe = 1)相连。
如果我的外键是“origin_id”,那么我很容易找到一个人的所有链接。但这只会显示起始于一个人的链接。在我的场景中,我需要查看所有链接,无论它们是由一个人发起还是接收。例如,如果我要求查看Sally的所有链接(Sally = 2),我想要的结果将是:
Links
+----+-----------+---------+
| id | origin_id | rcvd_id |
+----+-----------+---------+
| 1 | 2 | 1 |
+----+-----------+---------+
| 3 | 3 | 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),这与其限制调用的记录数以加快进程的速度背道而驰。而是在整个集合完成之后再限制记录。
此外,上面的代码将不允许我调用例如 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会排除所有其他sql修饰符,因为Rails不知道如何解析和修改提供的SQL。例如,我将无法在:finder_sql中使用:include选项。
所以,现在我正在使用:finder_sql解决方案。但似乎有一种方法可以完成此关联,而无需使用:finder_sql。例如,是否有一种方法编写自定义sql字符串,同时保留Active Record提供的Rails sql修饰符。
对以上内容有什么想法吗?