문제

Here is the way I've written my code:

sevendas = sixdas = fivedas = fourdas = threedas = twodas = onedas = todays = 0
@sat = List.all({:company_id => params[:id], :sat => true, :created_at => {:$gte => (time - 1.week)}})
@sat.each do |s|       
    if s["created_at"].strftime("%m-%d-%Y") == (time-1.week).strftime("%m-%d-%Y")
        sevendas += 1
    elsif s["created_at"].strftime("%m-%d-%Y") == (time-6.days).strftime("%m-%d-%Y")
        sixdas += 1
    elsif s["created_at"].strftime("%m-%d-%Y") == (time-5.days).strftime("%m-%d-%Y")
        fivedas += 1
    elsif s["created_at"].strftime("%m-%d-%Y") == (time-4.days).strftime("%m-%d-%Y")
        fourdas += 1
    elsif s["created_at"].strftime("%m-%d-%Y") == (time-3.days).strftime("%m-%d-%Y")
        threedas += 1
    elsif s["created_at"].strftime("%m-%d-%Y") == (time-2.days).strftime("%m-%d-%Y")
        twodas += 1
    elsif s["created_at"].strftime("%m-%d-%Y") == (time-1.day).strftime("%m-%d-%Y")
        onedas += 1
    elsif s["created_at"].strftime("%m-%d-%Y") == (time).strftime("%m-%d-%Y")
        todays += 1
    end
end
@tot_sat = []
@tot_sat.push( sevendas, sixdas, fivedas, fourdas, threedas, twodas, onedas, todays )

This works fine. What I'm working on now is improving my code and learning more efficient ways at writing these types of blocks.

I'm figuring that I can possibly use map here - it's the method of the day for me, trying to get a better handle on it.

도움이 되었습니까?

해결책

@tot_sat = @sat.group_by do |s|
  (time - s["created_at"]).to_i / 1.day
end.select do |diff, _| 
  diff < 8 
end.sort_by do |diff, _| 
  - diff 
end.map do |_, entries| 
  entries.count 
end

This solution groups the entries by the number of days difference from time, and then counts how many entries are in each day difference.


Update
The code above has a problem if not all the values (0-7) have entries. In this case, the array will be shorter. To avoid that, we'll use a different tactic in translating the grouped hash into the array:

grouped_sat = @sat.group_by do |s|
  (time - s["created_at"]).to_i / 1.day
end

@tot_sat = (0..7).map { |days| (grouped_sat[days] || []).count }

In this tactic, all values between 0 and 7, in turn, count the number of elements with the queried interval, defaulting at 0 (the length of the empty array), in the case there were no elements with the queried interval.

다른 팁

If you want to compare timestamps by date, use to_date. Without knowing anything else about the context of your code, it can be dramatically cleaned up just by computing s['created_at'].to_date once, and using a case statement:

sevendas = sixdas = fivedas = fourdas = threedas = twodas = onedas = todays = 0
@sat = List.all(company_id: params[:id], sat: true, created_at: {$gte: (time - 1.week)}})
today = time.to_date
@sat.each do |s|
  case s['created_at'].to_date
  when today - 1.week then sevendas += 1
  when today - 6.days then sixdas += 1
  when today - 5.days then fivedas += 1
  when today - 4.days then fourdas += 1
  when today - 3.days then threedas += 1
  when today - 2.days then twodas += 1
  when today - 1.day then onedas += 1
  when today then todays += 1
  end
end
@tot_sat = []
@tot_sat.push( sevendas, sixdas, fivedas, fourdas, threedas, twodas, onedas, todays )

You could further refactor it to drop the ugly sevendas = sixdas = fivedas = ... thing and just store the values in an array.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top