Preacher
Preacher

Reputation: 2420

How do I group and sort by a nested attribute in rails?

class BillableEvent < ActiveRecord::Base
  has_many :billable_jobs
end

class BillableJob < ActiveRecord::Base
  belongs_to :billable_event
  belongs_to :job
end

class Job < ActiveRecord::Base
  has_many :billable_jobs
  belongs_to :customer
  acts_as_list scope: :customer_id
  default_scope {order(:position)}
end

class Customer < ActiveRecord::Base
  has_many :jobs
end

class BillableEventController < ApplicationController
  def invoice
    @billable_jobs = @billable_event.billable_jobs
    @jobs = # ... what should I put here?
  end
end

In my view I'd like to see:

%table.invoice
  - @jobs.each do |job, billable_jobs|
    %tbody
      %tr.title
        %td.title{colspan: '4'}= job.stand_alone_title
      - billable_jobs.each do |billable_job|
        = content_tag_for(:tr, billable_job) do
          %td &nbsp;
          %td= billable_job.user.name
          %td= billable_job.billable_price
          %td= button_to 'Invoice'

For example:

Amber - Job 1
  A-BillableJob $10
  B-BillableJob $25
Amber - Job 2
  A-BillableJob $10
Paul
  A-BillableJob $25
  B-BillableJob $10

Where jobs are grouped and sorted by customers title. (The names above would be examples of the job's stand_alone_title, which is derived from the customer title.) Every way I know to group the jobs by customer converts it to a hash or array that I can't seem to sort properly.

Upvotes: 0

Views: 2306

Answers (1)

Nermin
Nermin

Reputation: 6100

You can do group_by and it will convert it to array, but you can then sort array with sort_by method that exist in an Array class.

class BillableEventController < ApplicationController
  def invoice
    @billable_jobs = @billable_event.billable_jobs
    # group records by customer
    customers = @billable_jobs.group_by{|e| e.job.customer}
    # when you call group_by it creates array
    # [<customer> => [<billable_j1>, <billable_j2>, ..], <customer_2> => [<billable_j>, ...]]
    @customers = jobs.sort_by{|customer, jobs| customer.title}
    # method sort_by from Array class sorts array
    # and takes argument to sort by
  end
end

Upvotes: 3

Related Questions