2013-10-15 69 views
1

我的車型有:最有效的軌道加入呼籲這種情況下

class Link < ActiveRecord::Base 
    has_many :votes 
    belongs_to :user 
end 

class Vote < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :link 
end 

class User < ActiveRecord::Base 

    has_secure_password 

    has_many :links 
    has_many :votes 
end 

我有一個頁面,我列出系統中的所有鏈接。對於每個鏈接,我希望顯示所有投票的當前總數以及提出請求的用戶是否對該特定鏈接進行投票(如果是,那麼投票的價值是多少)。我想以最有效的方式做到這一點。

目前爲了回報我有這個票的鏈接和資金在我的鏈路控制器:

def index 
    @links = Link.all(:joins => :votes, :select => "links.*, sum(votes.value) as votes_total", :group => "links.id") 
end 

效果很好,給我在一次調用所有的信息。所以我的問題是,我是否需要進行第二次查詢以返回current_user的投票(如果存在),還是可以將它合併到我的第一個查詢中?

此外,也許我應該在數據庫中設置某種sum_caching,但我不確定最好的方法去做。有什麼想法嗎?

回答

0

你可以做這樣的事情:

@links = Link. 
    joins(:votes). 
    select(
    "links.*, sum(votes.value) as votes_total, sum(case votes.user_id when #{current_user.id} then votes.value else 0 end) as current_vote", 
    :group => "links.id" 
) 

這將使你的當前用戶的投票價值@links.first.current_vote。當然,如果您的系統的投票值爲零,它不會區分「當前用戶在此鏈接投票0」和「當前用戶未在此鏈接投票」。我想,你可以添加另一個選定的值(sum(case votes.user_id when #{current_user.id} then 1 else 0 end) as current_vote_exists)來處理這個問題。

很自然地,當你像這樣插入SQL時,你要非常小心,並且/或者查找ActiveRecord附帶的SQL消毒工具。