似乎有很多方法可以處理多重外鍵關聯。我接觸過的每種方式都有他們的缺點,而且由於我是Rails的新手,我相信其他人也會遇到類似的情況,我可能正在研究很久以前解決的問題。Rails - 多重索引密鑰關聯
我的問題是:
什麼是處理多索引鍵關聯的有效途徑,同時仍然保留了所有其他的Rails SQL調節劑(如:包括等)?
我的情況是:
我有一個表的關聯如下(簡體),用於通過鏈路連接的人給其他人:
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的鏈接(莎莉= 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
然而,這是沒有效率的。例如,這需要從數據庫中收集整個集合,然後才能使用分頁方法(我使用的是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排除所有其他sql修飾符,因爲Rails 不知道如何解析和修改您提供的SQL。例如,我不能使用:include選項和:finder_sql。
所以,現在我正在使用:finder_sql,解決方案。但似乎可能會以這樣一種方式完成這種關聯:我不需要:finder_sql。例如,有沒有辦法在保留Active Record提供的Rails sql修飾符的同時編寫自定義的sql字符串。
以上任何想法?
謝謝Lelon。還沒有跳過它的Rails3(我知道,尷尬),但會很快看到這一點。 – Oscar 2010-12-06 05:14:15