Reputation: 533
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?
Upvotes: 5
Views: 355
Reputation: 1929
<% 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 %>
Upvotes: 2
Reputation: 101
Why you just can't order by two fields: by "day" and by "opening_hour"?
<% @merchant.working_hours.order(:day).order(:oppening_hour).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 %>
Upvotes: 0
Reputation: 101
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 %>
Upvotes: 2
Reputation: 1684
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.
Upvotes: 2