2013-10-15 69 views
2

我想更好地理解rails數據庫API。如果我有以下型號:Rails:包括所有的模型A和相關模型的一個子集B

class Link 
    has_many :votes 
    belongs_to :user 
end 

class Vote 
    belongs_to: link 
    belongs_to :user 
end 

class User 
    has_many :links 
    has_many :votes 
end 

我想「急切地」返回所有鏈接的列表和每個環節我想其中USER_ID等於當前用戶的投票。我試過這個:

l = Link.all(:include => :votes, :conditions => { :votes => { :user_id => current_user.id}}) 

但是,它只返回用戶提交投票的鏈接列表。我希望它返回全部鏈接,然後僅返回該用戶的投票(如果沒有,則爲none)。我如何用include語句來做到這一點?

+0

哪個版本的Rails是這個? – depa

+0

「希望它返回所有鏈接**,然後**僅爲該用戶投票」。聽起來就像你正在處理兩個單獨的查詢 – beautifulcoder

+0

@depa 3.2,但我也對第4版的解決方案感興趣。 beautifulcoder真的嗎?這不能在單個查詢中完成?我覺得很難相信。 – user1813867

回答

0

我不得不重讀這個問題幾次,所以請讓我知道如果我對此感到困惑。這聽起來像你想要使用LEFT OUTER JOIN。這將爲您提供links表中投票與用戶標識匹配的所有內容以及與curret用戶沒有投票匹配的所有其他鏈接。事情是這樣的:

Link.all(:include => :votes, 
:select=>"DISTINCT links.*", 
:joins => "LEFT OUTER JOIN votes ON links.id = votes.link_id AND votes.user_id = #{current_user.id}", 
:conditions=>"NOT EXISTS (SELECT * FROM votes WHERE votes.link_id = links.id) OR votes.user_id = #{current_user.id}") 

而且,因爲你已經在使用Rails 3.2,你可能會想使用新的活動記錄查詢方法,因爲我相信,基於舊的哈希查找方法是棄用軌道4,5所以同一個查詢應該是這樣的:

Link.include(:votes) 
.joins("LEFT OUTER JOIN votes ON links.id = votes.link_id AND votes.user_id = #{current_user.id}") 
.where("NOT EXISTS (SELECT * FROM votes WHERE votes.link_id = links.id) OR votes.user_id = #{current_user.id}") 
.uniq.load 

關於/ where部分,這將創建一個相關子查詢,這將導致Link行,如果在投票表中存在被拒絕的條件(意思是SOMEBODY投票在一點上),或者如果它確實存在,無論它是由我們指定的用戶投票。最終的結果是您獲得任何沒有任何投票的Link行,或與指定用戶創建的投票鏈接。

UPDATE

正如評論所說,這種方法的問題是相關的votes行並不急於根據需要加載。現在用這個工具約2個小時後,我幾乎承認,我不認爲有可能用這種查詢加載關聯的表。

如果我們溝include部分(這似乎沒有任何效果反正),我們找回已被指定的用戶投票,或沒有一個人Link對象的集合。問題在於,當我們調用.votes時,Rails樂意讓沿着SELECT votes.* FROM votes WHERE votes.link_id = [the link id]的行調用另一個數據庫,正如你所看到的,在這一點上不會被user_id區分。

我能想到的唯一解決方案就是在調用關聯方法時正確量化要查找的內容。事情是這樣的:

link.votes.where(:user_id=>current_user.id) 

這將產生一個這樣的查詢:

SELECT votes.* FROM votes WHERE votes.link_id = [the link ID] AND user_id = [the user ID] 

如果有人有更好的解決方案,我會希望看到它。

希望有所幫助。

+0

當我直接在SQL中執行操作時選擇links.title,votes.value從左連接投票(links.id = votes.link_id AND votes.user_id = 5);但是當我在rails中完成你的解決方案並將值賦給l然後輸入l [0] .votes我得到[#<投票ID:1,值:1,created_at:nil,updated_at:「2013-10-15 20 :42:06「,link_id:1,user_id:5>,#<投票ID:3,值:1,created_at:」2013-10-15 20:45:24「,updated_at:」2013-10-15 20 :45:24「,link_id:1,user_id:4>]這是從兩個不同的用戶返回投票....奇怪的不是? – user1813867

+0

@ user1813867廢話。是的,這是因爲與左連接的AND票。用戶ID部分。我只是在運輸過程中,所以給我幾分鐘,我會弄清楚 –

+0

@ user1813867看到我的更新...不完全是你想要的,但至少是它在「軌道」的做事方式。希望它有所幫助。 –

相關問題