Ask A Question


You’re not receiving notifications from this thread.

Group records by month to display in a chart

Francisco Quinones asked in General

Hi Chris Im using HighChart and I have some data that want to display in group by month.


You may have to adjust the hashes for HighCharts, but the groupdate gem is pretty good for this. It was designed for the Chartkick gem.


more details of my problem. Im looking for a way to make the code more dry, has I need to display all the Task, and Task by status. So your getting a bar chart with Task complete, Task Pending and Task cancel. With this code I can display alll task. so now how can I use this code but to display each status on the chart. without duplicating the code.


@months =
@total_tasks =
@tasks = Task.group_by { |t| t.start_date.strftime("%B/%Y")} 
@tasks.reverse_each do |key, value|
    @months << key
    @total_tasks << value.size

With this line I get the same output

   Task.group_by_month(:date, format: "%b %Y").count


<div id="chart_tasks" style="min-width: 210px; max-width: auto; height: 400px; margin: 0 auto"></div>
<%= javascript_tag do %>
   window.months = JSON.parse('<%= raw @months%>')
   window.total_tasks = JSON.parse('<%= raw @total_tasks%>')
<% end %>

$(function () {

        xAxis: {
            categories: months

        series: [{
                name: ' Task Total',
                type: 'column', 
                data: total_tasks,
                dataLabels: {
                        enabled: true,
                        color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'black'

I think you'll need to filter the array of tasks for each status, create variables for each of those, and then pass those in as different series to your chart.

    @finish , @unfinish = [], []
@tasks.each do |t|
    @finish << t if t.status == 'Complete'
    @unfinish << t if t.status == 'Cancel'

You can make that a bit easier if you do select too:

@tasks      = Task.group_by { |t| t.start_date.strftime("%B/%Y")} 
@finished   ={ |task| task.status == 'Complete' }
@unfinished ={ |task| task.status == 'Cancel' }

Nice more clean love it what I was looking. Chris Thank you for all the help for the pass few months. my app looks great with all the help.


You're welcome man! :)


Chris can I use any of this scope for that??

scope :cancel, lambda {where(:status => "Cancelada")}
scope :unfinish, lambda {where(:status => "Expirada")}
scope :pending, lambda {where(:status => "Pendiente")}
scope :finish, lambda {where(:status => "Completada")}
scope :transfer, lambda {where(:move_task => true)}

Yup! I would recommend doing scopes for this for sure.


Chris if I do.
@tasks = Task.group_by { |t| t.start_date.strftime("%B/%Y")}
@finished ={ |task| task.status == 'Complete' }

I get a error

   NoMethodError: undefined method `status' for "November/2015":String
from (irb):136:in `block in irb_binding'
from (irb):136:in `select'

I think that @tasks its using a K,V and when im reading the .select{ |task| task.status} its doing this

 k = "November/2015"

Ah yeah, your group_by is going to give you a hash. You probably want to do group_bys on those after filtering the queries to make it cleaner.


Chris How can I filter the queries with out duplicating the code so much as Im breaking my head. I like to keep it all dry up and few querys
can you giving me a example of your approach. thankyou.


I would do something like this (using the group_by_month method from groupdate so it's a bit cleaner).

@tasks    = Task.all.group_by_month(:date, format: "%b %Y").count
@finished = Task.finish.group_by_month(:date, format: "%b %Y").count
@unfinish = Task.unfinish.group_by_month(:date, format: "%b %Y").count

thankyou thats the best solution.

Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 83,038+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.