Many times we come across such situations where we need to group records, like when we want to display grouped messages, email, alerts .etc based on date or time. Here is the simple code which provides a significant use of group_by method.
Controller Part
class MessagesController < ApplicationController
def index
@message = Message.all
#Retrives all messages and divides into two groups todays messages and other messages
@grouped_messages = @message.group_by{ |t| t.created_at.to_date == DateTime.now.to_date }
if @grouped_messages[false].present?
#Create month wise groups of messages
@month_wise_sorted_alerts = @grouped_messages[false].group_by{ |t| t.created_at.month}
end
end
end
@message = Message.all
#Retrives all messages and divides into two groups todays messages and other messages
@grouped_messages = @message.group_by{ |t| t.created_at.to_date == DateTime.now.to_date }
if @grouped_messages[false].present?
#Create month wise groups of messages
@month_wise_sorted_alerts = @grouped_messages[false].group_by{ |t| t.created_at.month}
end
end
end
@message.group_by{ |t| t.created_at.to_date == DateTime.now.to_date }
The above line return us the messages in Ordered Hash with two keys true and false on which the messages which are of today's date will be values in true key and others will be values in false.
@grouped_messages[false].group_by{ |t| t.created_at.month }
Above line will provide us the monthwise sorting of the messsages. It will create the Ordered Hash with keys as the month numbers and values as the messages according to their month numbers.
View Part
<h1>Messages</h1>
<!-- Todays messages -->
<% if @grouped_messages.present? && @grouped_messages[true].present? %>
<h3> Today </h3>
<% @grouped_messages[true].each do |msg| %>
<%= msg.content %>
<%= msg.created_at.strftime('%I:%M %p') %>
<br />
<% end %>
<br />
<% end %>
<!-- Month wise sorted messages -->
<% if @month_wise_sorted_alerts.present? %>
<% @month_wise_sorted_alerts.each do |hash_elements|%>
<h3> <%= Date::MONTHNAMES[hash_elements.first] %> </h3>
<% hash_elements.last.each do |msg| %>
<%= msg.content %>
<%= msg.created_at.strftime('%b %d') %>
<br />
<% end %>
<br />
<% end %>
<% end %>
<!-- Todays messages -->
<% if @grouped_messages.present? && @grouped_messages[true].present? %>
<h3> Today </h3>
<% @grouped_messages[true].each do |msg| %>
<%= msg.content %>
<%= msg.created_at.strftime('%I:%M %p') %>
<br />
<% end %>
<br />
<% end %>
<!-- Month wise sorted messages -->
<% if @month_wise_sorted_alerts.present? %>
<% @month_wise_sorted_alerts.each do |hash_elements|%>
<h3> <%= Date::MONTHNAMES[hash_elements.first] %> </h3>
<% hash_elements.last.each do |msg| %>
<%= msg.content %>
<%= msg.created_at.strftime('%b %d') %>
<br />
<% end %>
<br />
<% end %>
<% end %>
We can use rails helper to get the month name Date::MONTHNAMES[--month_number--] to get the name of the month in the view.
References:
- http://apidock.com/rails/Enumerable/group_by
Good stuff with a scope for improvement. This is very specific implementation with an opportunity to be generalized for different purposes. For example, the same code/logic can be used for month_wise_sorted_alerts and grouped messages.
ReplyDeleteThanks! Will surely keep in mind.
DeleteHi, just wanted to tell you, I enjoyed this blog post.
ReplyDeleteThanks Olivia :)
DeleteWhat a commendable work you have done, with simplest of language. Great piece of writing, Awesome stuff.
ReplyDeleteTHE #1 MEDICAL WEBSITE DESIGN for all kind of medical offices and specialists.
Thanks Maria :)
Delete