2017-01-18 54 views
1

我是相當新的rails &我遇到了這個性能問題,我將不勝感激任何幫助。Rails急需爲現有對象加載has_many關聯

我有一個用戶模型&每個用戶has_many關聯UserScores。我正準備顯示不同用戶統計信息的儀表板,其中包括基於特定條件的user_scores計數。下面是代碼片段:

def dashboard 
@users = Array.new 
users = User.order('created_at ASC') 
users.each do |u| 
    user = {} 
    user[:id] = u.id 
    user[:name] = u.nickname 
    user[:email] = u.email 
    user[:matches] = u.user_scores.count 
    user[:jokers_used] = u.user_scores.where(:joker => true).length 
    user[:jokers] = u.joker 
    user[:bonus] = u.user_scores.where(:bonus => 1).length 
    user[:joined] = u.created_at.strftime("%y/%m/%d") 
    if user[:matches] > 0 
     user[:last_activity] = u.user_scores.order('updated_at DESC').first.updated_at.strftime("%y/%m/%d") 
    else 
     user[:last_activity] = u.updated_at.strftime("%y/%m/%d") 
    end 
    @users << user 
end 
@user_count = @users.count 

我看到重複UserScore的數據庫查詢爲每個用戶獲得不同的計數問題。

有沒有辦法避免這些多重查詢?

N.B.我不知道如果我爲視圖準備數據的方法是最佳的方式,因此任何建議或有關該提示將不勝感激,以及。

感謝

回答

0

首先,參考user_scores協會在您的查詢:

users = User.includes(:user_scores).order('created_at ASC') 

關注Rails文檔關聯預先加載:http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations

還要注意的是where,使新的數據庫查詢,即使你關聯已經預先加載。因此,與其

u.user_scores.where(:joker => true).length 
u.user_scores.where(:bonus => 1).length 

嘗試:

u.user_scores.count { |us| us.joker } 
u.user_scores.count { |us| us.bonus == 1 } 

你可能會改寫.user_scores.order('updated_at DESC').first.updated_at.strftime("%y/%m/%d")莫名其妙以及

+0

我試過了,但仍然user_scores的多個查詢正在發生的每個用戶 – PeterB

+0

因爲'where'使得即使您的關聯已經預裝到新的數據庫查詢。代替 'u.user_scores.where(:百搭=>真).length' 和'u.user_scores.where(:獎金=> 1)。長度' 嘗試: 'u.user_scores.any? {| us | us.joker}' 和'u.user_scores.any? {| us | us.bonus == 1}' 您可能不得不重寫'.user_scores.order('updated_at DESC')。first.updated_at.strftime(「%y /%m /%d」)'不知何故 –

+0

嘗試它並給我這個錯誤 錯誤的參數數量(1爲0) – PeterB

1

你需要熱切地加載users_scores來減少多個查詢。 @ Slava.K就如何消除這個問題提供了很好的解釋。 爲查詢用戶添加includes(:user_scores),並且一旦通過查詢從數據庫中提取數據,就使用ruby的方法處理集合。

見下面的代碼來理解:

users = User.includes(:user_scores).order('created_at ASC') 

users.each do |u| 
    .... 

    user[:matches] = u.user_scores.length 
    user[:jokers_used] = u.user_scopes.select{ |score| score.joker == true }.length 
    user[:jokers] = u.joker 
    user[:bonus] = u.user_scores.select{ |score| score.bonus == 1 }.length 
    .... 
end 

而且,你正準備迴應的方式是不乾淨,靈活。相反,您應該重寫as_json方法來準備可正確使用視圖的json。 as_json方法默認爲模型定義。你可以閱讀更多關於它從官方文檔http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html或訪問article on preparing clean json response,我約了深入的正常覆蓋as_json解釋。

+0

Thx Parth將檢查你指向的資源 – PeterB

+0

你能否請添加一個參考如何在HTML視圖中使用JSON響應? – PeterB

+0

as_json將返回散列,它可用於準備響應或可用作您在問題中使用的變量。 –

相關問題