Skip to content

Instantly share code, notes, and snippets.

@kopylovvlad
Last active May 16, 2017 18:43
Show Gist options
  • Save kopylovvlad/5bd63bb27962f43429db2857bfd066b3 to your computer and use it in GitHub Desktop.
Save kopylovvlad/5bd63bb27962f43429db2857bfd066b3 to your computer and use it in GitHub Desktop.
# app/model/weekly_day.rb
WeeklyDay = Struct.new(:start_day, :end_day) do
def start_day_string
start_day.strftime('%A %d-%m-%Y')
end
end
# app/model/daily_statistic.rb
DailyStatistic = Struct.new(:day_string, :orders) do
def day
day_string
end
def orders_sum
@orders_sum ||= orders.map(&:price).reduce(:+)
end
def pizza_count
@pizza_count ||= orders
.map { |order| order.items.where(type: :pizza).count }
.reduce(:+)
end
def users
@users ||= get_users_arr
end
def pizza
@pizza ||= get_pizza_arr
end
private
##
# returns array
# like this
# [ { pizza: <Item>, count: 10},
# { pizza: <Item>, count: 8},
# { pizza: <Item>, count: 7},]
def get_pizza_arr
pizza_hash = Hash.new(0)
orders
.map { |order| order.items.where(type: :pizza) }
.reduce(:+).each { |item| pizza_hash[item.id] += 1 }
pizza_hash = pizza_hash.sort_by { |k, v| v }.reverse.to_h
Hash[pizza_hash.sort_by { |k,v| -v }[0..2]].map do |k,v|
{
pizza: Item.find(k),
count: v
}
end
end
##
# return array like this
# [ {user: <User>, sum: 1000},
# {user: <User>, sum: 900},
# {user: <User>, sum: 850}]
def get_users_arr
users_hash = Hash.new(0)
orders.each { |order| users_hash[order.user_id] += order.price }
users_hash = users_hash.sort_by { |k, v| v }.reverse.to_h
Hash[users_hash.sort_by { |k,v| -v }[0..2]].map do |k,v|
{
user: User.find(k),
sum: v
}
end
end
end
# app/models/weekly_statistic.rb
class WeeklyStatistic
def perform
date.map do |weekly_day|
DailyStatistic.new(
weekly_day.start_day_string,
get_orders(weekly_day)
)
end
end
def date
@date ||= get_date
end
private
##
# it returns something like this
# [ <WeeklyDay>, <WeeklyDay>, <WeeklyDay> ]
def get_date
arr = []
start_day = nil
loop do
unless start_day.present?
start_day = DateTime.current.beginning_of_week
else
start_day += 1.day
end
end_day = start_day + 1.day
arr.push(WeeklyDay.new(start_day, end_day))
break if end_day > DateTime.current.end_of_week
end
arr
end
def get_orders(date_obj)
Order.preload(:user, :items).where(
'created_at >= :start_day AND created_at < :end_day',
start_day: date_obj.start_day,
end_day: date_obj.end_day
)
end
end
# app/controllers/statistics_controller.rb
class StatisticsController < ApplicationController
# ...
def weekly
@weekly = WeeklyStatistic.new.perform
end
# ...
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment