Elvyn Mejia
Elvyn Mejia

Reputation: 317

Rails many-to-one relationship aggregate functions (group, count) active record

I have two models in a many-to-one relationship:

class Event
  has_many :comments 
end

class Comment
  # notice enum for comment status: pending => 0, approved => 1
  enum status: [:pending, :approved]
  belongs_to :event
end 

I would like to get some comment stats on a given event. For example for event with id 1, find all of its comments and calculate how many comments are pending and approved. e.g return data for event with id 1 and its comment stats

    [
      id: 1, #event id and all event related data 
      comment_stats = { pending: 3, approved: 20} 
   ]

Also the data should contain all the Event fields as well as a comment_stats hash

I am stuck as to what approach to take.

My first attempt is as follow

event = Event.find(params[:id])
event.messages.select(:status)

Here is where I need to do the grouping and count comment stats for event with id 1.

This gives me back an array of messages e.g.

    [
      { " id":null, "status": "pending"}, 
      { "id": null, "status": "approved"} ...
   ]

Here I would like to group this array of hashed as such:

comment_stats = { pending: 3, approved: 20}

I am really out of idea. I'd greatly appreciate any help I can get.

Upvotes: 1

Views: 259

Answers (1)

Andrey Deineko
Andrey Deineko

Reputation: 52367

class Event
  def stats
    {
      event_id:      id,
      event:         self,
      comment_stats: {
        pending:  comments.where(status: Comment.statutes[:pending]).count,
        approved: comments.where(status: Comment.statutes[:approved]).count
      }
    }
  end
end

Usage:

event = Event.find(params[:id])
event.stats
#=> { event_id: 1, event: <Event object>, comment_stats: { pending:  10, approved: 20 } }
event.stats[:comment_stats]
#=> { pending:  10, approved: 20 }

Upvotes: 1

Related Questions