vidal vidal - 2 months ago 8
Ruby Question

Group where no appointment

The code below shows number of appointment each hour and 'No appointment' if no appointment is available.

I want to group consecutive 'No appointment' slot according to time

for e.g., The output of the current code is -

10:00 AM to 11:00 AM -> No Appointment
11:00 AM to 12:00 PM -> No Appointment
12:00 PM to 01:00 PM -> No Appointment


I want the output to be

10:00 AM to 01:00 PM -> No Appointment


The code is give below:-

<% @time_group = ['6:00:00','7:00:00','8:00:00','9:00:00','10:00:00','11:00:00','12:00:00','13:00:00','14:00:00','15:00:00','16:00:00','17:00:00','18:00:00','19:00:00','20:00:00','21:00:00','22:00:00','23:00:00'] %>

#Loop through each hour in @time_group
<% @time_group.each_with_index do |t,index| %>
<% t1 = Time.parse(t) %>
<% t2 = Time.parse(t) + 3600 %>
<% @booked = Appointment.where(start_time: t1..t2 %>

#Show time interval e.g 1:00 PM to 2:00 PM
<%= Time.parse(t).strftime('%I:%M %p') %> to <%= (Time.parse(t) + 3600).strftime('%I:%M %p') %>

#if appointment is available show appointment else show no appointment
<% if @booked.size > 0 %>

<% @booked.each do |app| %>
<%= app.start_time.strftime('%I:%M') %>
<% end %>

<% else %>

No Appointment

<% end %>
<% end %>

Answer

First of all, one might prepare the array:

@time_group = ['6:00:00','7:00:00', ...]
@stacked = @time_group.each_with_object([]) do |start, memo|
  range = Time.parse(start)..Time.parse(start)+3600
  booked = Appointment.where(start_time: range)
  if memo.empty? || !booked.empty? || !memo.last.last.empty?
    memo << [range, booked] # no sequenced empty slots
  else
    memo << [memo.pop.begin..range.end, booked] # merge ranges
  end
end.to_h # { ranges => booked }

And now—let’s output them:

<% @stacked.each do |range, booked| %>
  .....
<% end %>