I am pretty new to ROR and Postgre and i'm in trouble to achieve this.
I have a Working_hour Model and a Merchant Model, where merchant has_many working_hours and working_hour belongs to Merchant. The merchant can have two or mores working_hours for the same day.
My view:
<% @merchant.working_hours.order(:day).group_by(&:day).each do |dia, whs| %>
<%= t(:"date.abbr_day_names")[dia.to_i] %> :
<% whs.each do |wh| %>
<li>
<%= wh.oppening_hour.to_formatted_s(:time) %> -
<%= wh.close_hour.to_formatted_s(:time) %>
</li>
<% end %>
<% end %>
When I display at the view ordered by day the data retrieved are (note that the opening hour are unordered):
Mon:
17:00-20:00
10:00-13:00
Tue:
18:00-21:00
10:00-13:00
I want to group by day of week and ordering first by day of week and second by opening hour :
Mon:
10:00-13:00
17:00-20:00
Tue:
10:00-13:00
18:00-21:00
But as you can see, currently, I'm using the ruby layer to do that what brings performance issues. How can achieve this using the database layer?
Quick Postgres example if you're willing to store the data in DB table (on randomly created dataset):
-- The query:
SELECT to_char( mytime, 'day' ) as weekday, -- example to get weekday name
extract( dow from mytime ) as weekday_num, -- example to get weekday number
format( -- format the way example output was given
'%s - %s',
date_trunc( 'hour', opening_time )::time(0), -- get opening hour (without milliseconds)
date_trunc( 'hour', closing_time )::time(0) -- get closing hour (without milliseconds)
) as working_hours
FROM mytable
GROUP BY mytime, -- to secure accurate ordering by timestamp
weekday,
working_hours
ORDER BY mytime,
working_hours;
-- Result:
weekday | weekday_num | working_hours
-----------+-------------+---------------------
monday | 1 | 08:00:00 - 17:00:00
tuesday | 2 | 08:00:00 - 16:00:00
tuesday | 2 | 08:00:00 - 17:00:00
wednesday | 3 | 08:00:00 - 12:00:00
thursday | 4 | 08:00:00 - 12:00:00
thursday | 4 | 08:00:00 - 16:00:00
friday | 5 | 08:00:00 - 15:00:00
friday | 5 | 08:00:00 - 18:00:00
Postgres documentation links that might come handy:
https://www.postgresql.org/docs/current/static/functions-datetime.html https://www.postgresql.org/docs/current/static/functions-formatting.html https://www.postgresql.org/docs/current/static/functions-string.html#FUNCTIONS-STRING-FORMAT
P.S. Hopefully gives some ideas how to solve it in database.
The working hour should be ordered by opening_hour as you will show the opening hour in UI in ascending order. Once the working hour is ordered, the result can be grouped by day.
<% @merchant.working_hours.order(:opening_hour).group_by(&:day).each do |dia, whs| %>
<%= t(:"date.abbr_day_names")[dia.to_i] %> :
<% whs.each do |wh| %>
<li>
<%= wh.opening_hour.to_formatted_s(:time) %> -
<%= wh.close_hour.to_formatted_s(:time) %>
</li>
<% end %>
<% end %>
<% day = nil %>
<% @merchant.working_hours.order(:day, :oppening_hour).each do |wh| %>
<% if wh.day != day %>
<% day = wh.day %>
<%= t(:"date.abbr_day_names")[day.to_i] %> :
<% end %>
<li>
<%= wh.oppening_hour.to_formatted_s(:time) %> -
<%= wh.close_hour.to_formatted_s(:time) %>
</li>
<% end %>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With