Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails ActiveRecord group results into sub-collections by date

I'm trying to do an ActiveRecord query in Rails 3.1 where I sort the results into sub-collections of grouped items, in this case grouped by date.

I think my code can explain it best. This is my method, which works but issues 4 queries to get the job done. It doesn't seem very efficient to do it this way.

def entry_days
  days = @user.entry_groups.find(
    :all,
    :select => 'date',
    :limit => 3,
    :group => 'date').map(&:date)

  entry_days = days.map do |date|
    { :date =>  date,
      :entry_groups => @user.entry_groups.find_all_by_date(date)
    }
  end      
end

Using the suggestion from Dave Newton below to use group_by, I have re-written the method like this:

def entry_days
  dates_with_entries = @user.entry_groups.find(
    :all,
    :select => 'date',
    :limit => 3,
    :group => 'date').map(&:date)

  @user.entry_groups.where(:date => dates_with_entries).all.group_by(&:date).
    map do |date, entry_groups|
      { :date => date,
        :entry_groups => entry_groups }
    end
end

At least I have it down to only 2 queries now.

Then I re-wrote the method again like this:

  dates_with_entries = user.entry_groups.all(
      :select => 'date',
      :limit => num_days,
      :order => 'date DESC',
      :group => 'date').map(&:date)

  entry_groups = user.entry_groups.
      where(
        :date => dates_with_entries
      ).
      all(:order => 'date DESC')

  entry_days = entry_days.group_by(&:date).
      map { |date, entry_groups|
        {
          :date => date,
          :entry_groups => entry_groups
        }
      }

On a side note: Should I not be chaining so many methods together, and what is the preferred indentation format for nested methods and hashes?

like image 530
Chris M. Welsh Avatar asked Sep 05 '11 00:09

Chris M. Welsh


1 Answers

Why not select them all then use something like group_by?

like image 121
Dave Newton Avatar answered Nov 05 '22 14:11

Dave Newton