Informatika Mihelac
May 12 2007 rails | ruby | tips

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.

comments feed

6 comments

  1. # On July 14, 2007 at 19:07 PM, Brandon Keepers said:

    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%>
    
  2. # On July 15, 2007 at 08:07 AM, bmihelac said:

    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.

  3. # On November 28, 2007 at 11:11 AM, Bischov said:

    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!

  4. # On December 17, 2007 at 03:12 AM, astrid said:

    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

  5. # On December 18, 2007 at 07:12 AM, Bojan Mihelac said:

    Bischov, what you have in block that you are sending to classify?

  6. # On February 01, 2008 at 22:02 PM, myname said:

    really nice one

Speak your mind:

(Required)

(Required)


(You may use textile in your comments.)

About

I am Bojan Mihelac and this blog is dedicated to share code, thoughts, tools and advices I came up with while working in Informatika Mihelac.

Contact: bmihelac@mihelac.org

RSS feedSubscribe to RSS Feed