Tolga
Tolga

Reputation: 1357

Rails: How to sort based on Average, Sum, Count with Associated Models?

I have 2 associated tables as follows, and currently I have a reporting page which displays average, count, sum etc.. I would like to add sorting functionality to all columns on the report table but I couldn't figured out how I can achieve it for ave,count,sum calculations on the model?

DB TABLES:

Student
------
id
name
city

Course
------
id
coursename
price
status
student_id


MODELS:

class Student < ApplicationRecord
    has_many :course

class Course < ApplicationRecord
    belongs_to :student
    scope :ongoing, lambda {|ongoing| where(:status => ongoing)}
    scope :finished, lambda {|finished| where(:status => finished)}

VIEW:

<% @students.each do |student| %>
  <div class="row">
    <span><%= student.id %></span>
    <span><%= student.city %></span>
    <span><%= student.name %></span>
    <span><%= student.course.ongoing.count(:coursename) %></span>
    <span><%= student.course.ongoing.average(:price) %></span>
    <span><%= student.course.ongoing.sum(:price) %></span>
    <span><%= student.course.finished.count(:coursename) %></span>
    <span><%= student.course.finished.sum(:price) %></span>

Upvotes: 0

Views: 218

Answers (2)

EJAg
EJAg

Reputation: 3298

I'd recommend sorting it with js on the user end. Create a table and you can use one of many js sorting plugins to allow user to sort based on any columns they choose.

Alternatively you can sort @student with scope:

## Student
  scope :by_ongoing_course_count, -> {
    select(:id, :city, :name).joins(:courses).merge(Course.ongoing).group(:student_id).order("count(coursename)")
  }
end

## StudentsController
  def index
    @students = Student.by_ongoing_course_count
  end

By the way I think it's perfectly find to call instance methods in views. But you might want to create some helpers for those chained queries, e.g.

#Student
  def ongoing_course_counts
    course.ongoing.count(:coursename)
  end

Upvotes: 1

Ketan Doshi
Ketan Doshi

Reputation: 121

First of all create a method (for eg: get_student_data) in Student class which will provide you all the required data. Method should accept a parameters as well. Its always bad practice to call model methods or do queries in views.

Now once you get the required data from database, iterate through the data and sort it based on the sorting column passed in as a parameter.

Upvotes: 1

Related Questions