Rails in practice - Group records by condition
Often, when it comes to views I have to group records and present it to the user grouped by some condition. For example, I would like to list all news articles grouped by year.
To accomplish this, I find it easiest that records are grouped in a hash, key should be year when article is published and value would be array of objects matching published on these year.
Before, I used custom function that would walk throught all elements of array calling custom block for each member and creating new hash with result value of the block as key and array of elements as value.
Today I discover classify method in Set class that would do just what I need (thanks to Ruby Cookbook for that).
So, the code to group all news articles by year published is:
@groups = NewsArticle.find(:all).to_set.classify {
|article| article.published_on.year}
and view would be something like these:
<%@groups.each do |year, articles|%>
<h1><%=year%></h1>
<%=articles.collect {|a| \"<p>a.name</p>\"}.join%>
<%end%>
Short and sweet. Same method can be used to group anything, names by first letter, products by price range, etc.
I am Bojan Mihelac and this blog is dedicated to share code, thoughts, tools and advices I came up with while working in
6 comments
Enumberable also defines group_by, which does something similar, but uses an array of arrays which, unlike, hash, is ordered.
@groups = NewsArticle.find(:all).group_by {|article| article.published_on.year} <%@groups.each do |(year, articles)|%> <h1><%=year%></h1> <%=articles.collect {|a| \"<p>a.name</p>\"}.join%> <%end%>Good point Brandon. group_by method of Rails extension to Enumerable can also be used (and is more readable too), but still it returns hash and not array. If you sort hash you would get nested array.
Hi,
thanks for this – it’s really needed a lot. But with the first method (.to_set.classify), I have a problem, it will only return the first group, instead of all the groups.
I am creating the sets on a varchar column like this:
week52 title1 title2 title3 week51 title1 title2 week49 title1 title2 title3
...and so on…with your example, only week52 is in the returned set.
when I use Brandon’s method, all groups are returned, but as you said it, unsorted, which is no good for me.
Please help!
Good Day! To use credit cards or cash is the own choice of everyone. For me it is more convenient to purchase and travel with credit cards. I carry cash very seldom because today credit cards are available almost everywhere. I am going to Spain this vacation and yesterday applied for a new credit card at
discover card balance transfer check
Bischov, what you have in block that you are sending to classify?
really nice one
Speak your mind: