В настоящее время я пытаюсь реорганизовать какой-то старый код, который показывает панель управления для менеджера.
Пользователь отправляет множество электронных писем, связанных с бронированием еды, которые в основном хранятся в целях аудита.Мы отслеживаем количество электронных писем, отправленных каждому пользователю, и значение этого бронирования, сгруппированные по email_type
. В настоящее время ActiveRecord получает каждое электронное письмо с предложением where для фильтрации по create_at, а затем rails добавляет в массивкоторый затем выводится в таблицу.Это кажется действительно неэффективным, и Nginx истекает, поэтому мы не можем видеть результаты
Мне кажется, что использование в основном ActiveRecord с некоторыми группами значительно упростит все это.
Я только что добавил ассоциацию к user.rb следующим образом - потому что ее не былона месте (!) и в настоящее время он не используется:
has_many :emails, :foreign_key => "triggered_by_id"
В настоящее время MVC выглядит так:
Модель - email.rb:
scope :sent_between, -> ( start_date, end_date ) { where("emails.created_at >= ? AND emails.created_at <= ?", start_date, end_date) }
def self.sent_today
sent_between(DateTime.now.beginning_of_day, DateTime.now.end_of_day)
end
def self.metric_hash
{
"venue_confirmation" => [0, 0],
"enquiry_confirmation" => [0, 0],
"menu_verification" => [0, 0],
"amendment_information" => [0, 0],
"amendment_confirmation" => [0, 0],
"booking_confirmation_to_venue" => [0, 0],
"released_confirmation_to_venue" => [0, 0],
"cancellation_confirmation_to_venue" => [0, 0],
"transfer" => [0, 0],
"total" => [0, 0]
}
end
def self.type_for_metrics(email)
if %w(released_confirmation_to_venue cancellation_confirmation_to_venue).include?(email.email_type)
return "transfer" if email.booking.transferred_at
end
email.email_type
end
def self.metrics(start_date, end_date)
metrics = {}
totals = metric_hash
observed_bookings = Set.new
Email.includes(:booking).select(:id, :email_type, :triggered_by_id, :booking_id).sent_between(start_date, end_date).references(:booking).select(:booking_total).find_each do |email|
email_type = type_for_metrics(email)
if totals.has_key?(email_type)
metrics[email.triggered_by_id] ||= metric_hash
metrics[email.triggered_by_id][email_type][0] += 1
metrics[email.triggered_by_id][email_type][1] += email.booking.booking_total
metrics[email.triggered_by_id]["total"][0] += 1
metrics[email.triggered_by_id]["total"][1] += email.booking.booking_total
totals[email_type][0] += 1
totals[email_type][1] += email.booking.booking_total
totals["total"][0] += 1
# Only count the each booking once for the total value
unless observed_bookings.include?(email.booking_id)
totals["total"][1] += email.booking.booking_total
observed_bookings << email.booking_id
end
end
end
results = metrics.inject({}) do |memo, row|
if row[1]["total"][0] > 0
if row[0]
user = User.find(row[0])
memo[user.name] = row[1]
else
memo["Sent Before Tracking"] = row[1]
end
memo
end
end
results["Total"] = totals
results
end
index_controller.rb:
def metrics
@start = ( params[:start] && Time.zone.parse(params[:start]) ) || DateTime.now.start_of_period
@end = ( params[:end] && Time.zone.parse(params[:end]) ) || DateTime.now.end_of_period
@email_metrics = Email.metrics(@start, @end)
end
_metrics.html.erb
<h2>Emails Sent</h2>
<table>
<thead>
<tr>
<th></th>
<th title="New Enquiry">New</th>
<th title="Menu Confirmation">Menu</th>
<th title="Operator Confirmation">Confirm</th>
<th title="Released Enquiry">Released</th>
<th title="Cancelled Booking">Cancelled</th>
<th title="Amendment Information">Amend Info</th>
<th title="Amendment Confirmation">Amend Confirm</th>
<th title="Transferred">Transfer</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<% @email_metrics.each do |key, metrics| %>
<tr>
<th rowspan="2"><%= key %></th>
<td><%= metrics["venue_confirmation"][0] %></td>
<td><%= metrics["menu_verification"][0] %></td>
<td><%= metrics["booking_confirmation_to_venue"][0] %></td>
<td><%= metrics["released_confirmation_to_venue"][0] %></td>
<td><%= metrics["cancellation_confirmation_to_venue"][0] %></td>
<td><%= metrics["amendment_information"][0] %></td>
<td><%= metrics["amendment_confirmation"][0] %></td>
<td><%= metrics["transfer"][0] %></td>
<td><%= metrics["total"][0] %></td>
</tr>
<tr>
<td><%= number_to_currency metrics["venue_confirmation"][1] %></td>
<td><%= number_to_currency metrics["menu_verification"][1] %></td>
<td><%= number_to_currency metrics["booking_confirmation_to_venue"][1] %></td>
<td><%= number_to_currency metrics["released_confirmation_to_venue"][1] %></td>
<td><%= number_to_currency metrics["cancellation_confirmation_to_venue"][1] %></td>
<td><%= number_to_currency metrics["amendment_information"][1] %></td>
<td><%= number_to_currency metrics["amendment_confirmation"][1] %></td>
<td><%= number_to_currency metrics["transfer"][1] %></td>
<td>N/A</td>
</tr>
<% end %>
</tbody>
</table>
</div>
Мне кажется, что я бы начал с User.emails.etc ... но я получаюзастрял с несколькими group_by и массивно сложным массивом в настоящее время на месте.
Вот скриншот того, как это должно выглядеть.В среде разработки только один пользователь.
Снимок экрана: как должны выглядеть данные