2016-04-29 84 views
2

上下文: 試圖產生與用於每個created_at一天分貝表1個元件的陣列。每個元素是來自created_at天的記錄的points(整數)列的平均值。 這將稍後繪製成每天顯示點數的平均值。生成從數據庫表(Rails)的每日平均值數組

結果: 我已經成功地做到了這一點,但感覺就像不必要的代碼量來產生所需的結果。

代碼:

def daily_avg 
    # get all data for current user 
    records = current_user.rounds 

    # make array of long dates 
    long_date_array = records.pluck(:created_at) 

    # create array to store short dates 
    short_date_array = [] 

    # remove time of day 
    long_date_array.each do |date| 
     short_date_array << date.strftime('%Y%m%d') 
    end 

    # remove duplicate dates 
    short_date_array.uniq! 

    # array of avg by date 
    array_of_avg_values = [] 

    # iterate through each day 
    short_date_array.each do |date| 
     temp_array = [] 

     # make array of records with this day 
     records.each do |record| 
      if date === record.created_at.strftime('%Y%m%d') 
       temp_array << record.audio_points 
      end 
     end 
     # calc avg by day and append to array_of_avg_values 
     array_of_avg_values << temp_array.inject(0.0) { |sum, el| sum + el }/temp_array.size 
    end 
    render json: array_of_avg_values 
end 

問題: 我覺得這是一個常見的extraction問題需要通過大量的應用程序來解決,所以我不知道是否有解決一個已知的重複模式像這樣?

還是更理想的解決方法?

(我幾乎沒有一個初級開發者,所以你可以分享任何建議,將不勝感激!)

回答

2

是的,這是一個很大的不必要的東西時,你可以去到SQL做到這一點(我假設你在你的應用程序有一個名爲Round類):

class Round 

    DAILY_AVERAGE_SELECT = "SELECT 
     DATE(rounds.created_at) AS day_date, 
     AVG(rounds.audio_points) AS audio_points 
    FROM rounds 
    WHERE rounds.user_id = ? 
    GROUP BY DATE(rounds.created_at) 
" 

    def self.daily_average(user_id) 
    connection.select_all(sanitize_sql_array([DAILY_AVERAGE_SELECT, user_id]), "daily-average") 
    end 

end 

做直入本數據庫會比現在做的更快(並且包含更少的代碼),而不是像Ruby那樣。

+0

將created_at轉換爲剛剛從日期時間約會? –

0

我建議你做這樣的事情:

grouped = 
records.order(:created_at).group_by do |r| 
    r.created_at.strftime('%Y%m%d') 
end 

起初在這裏你生成正確的SQL接近你希望得到的第一個近似值,然後將created_at字段的結果記錄轉換成只是一個日期。

points = 
grouped.map do |(date, values)| 
    [ date, values.reduce(0.0, :audio_points)/values.size ] 
end.to_h 

# => { "1-1-1970" => 155.0, ... } 

然後,您通過數組重新映射您的分組散列,以計算audio_points的平均值。