Question

I have two active records StudentDemographics and StudentWeeklyReport both having has_many relation like this:

class StudentDemographics < ActiveRecord::Base
  has_many :student_weekly_reports, :foreign_key => :student_id
end

I have to check marks for each student in the last fifth week seminar with the latest one. If the result is true, student should be active, else inactive. I have the following code. Here, I am repeating the loop with each date. @distinct is an array of dates.

 for i in 0...@distinct.length
     active = 0
     inactive = 0
     sum = safe.length
     @students = StudentDemographics.where("date <= ?", @distinct[i]).select("student_id") - safe
     @students.each do |student|
        @stu = StudentWeeklyReport.where(:student_id => student.student_id).select("student_id,golden_eggs").last(5)
            if @stu.length > 4
                if @stu[4].golden_eggs > @stu[0].golden_eggs
                  safe << student
                  active += 1
                else
                  inactive += 1
                end
            else
                safe << student
                active += 1
            end
      end
      @active[i] = active + sum
      @inactive[i] = inactive
end

The performance is not good. It's taking more than 3 secs of time.my mysql db having 13600 in StudentWeeklyReports table and 2000 in StudentDemographics table. Can anyone suggest how to optimize the following code?

Was it helpful?

Solution

     @students = StudentDemographics.includes(:student_weekly_reports) - safe
 for i in 0...@distinct.length
     active = inactive = 0
     @students.each do |student|
        next if student.date > @distinct[i]
        @stu = student.student_weekly_reports.select("golden_eggs").last(5)
            if @stu.length > 4 && (@stu[4].golden_eggs <= @stu[0].golden_eggs)
                inactive += 1
            else
                safe << student
                active += 1
            end
      end
      @active[i] = active + safe.length
      @inactive[i] = inactive
end

OTHER TIPS

@students = StudentDemographics.includes(:student_weekly_reports).where("date <= ?", @distinct.min).select("student_id")
# The above line will fetch all the necessary records you require 

for i in 0...@distinct.length
 active = inactive = 0
 @students = @student.select { |student_demographics| student_demographics.date <= @distinct[i] } - safe
 @students.each do |student|
   @stu = student.student_weekly_reports.select("golden_eggs").last(5)
   if @stu.length > 4 and (@stu[4].golden_eggs <= @stu[0].golden_eggs)
     inactive += 1
   else
     safe << student
     active += 1
   end
  end
  @active[i] = active + safe.length
  @inactive[i] = inactive
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top