Count associations in a Ruby model I'm trying to figure out if there's a better way to run the code below.
Basically Course is an association of Student and courses_needed is an array of Course where I have many Students have and need many Courses and I'm trying to figure out the demand.
I've came up with the following code and it runs, which is fine, but when I want to display it on a statistics page with 36 Courses, the same code needs to be run once for each Course. 

I've solved it now by having it run once a day, instead of real-time.

  def self.calculate_needed
    Course.all.each do |course|
      neededArray = Array.new
      needed = 0
      Student.all.each do |s|
        unless s.courses_needed.nil?
          s.courses_needed.each do |c|
            if c == course
              needed += 1
            end
          end
        end
      end
      course.needed = needed
      course.save
    end
  end
This should be interesting. The fastest way I can think of is to pluck all the courses_needed arrays out of Student, group them together, and count them:

course_hash = Student.where.not(courses_needed: nil).pluck(:courses_needed).
  flatten.group_by { |c| c }.map { |k, v| [k, v.size] }.to_h


Essentially, I grab all students that actually have courses_needed, I then grab just all the courses needed from students. Flatten the course arrays so that all courses are within the same array, then I group them by course. After that I map again to replace the values (just the list of all same courses) with the number of times each course is listed. Then I do to_h to turn each [course, number] into a course => number hash that you can access easier.

So pluck returns:

[[course, course2, course3], [course, course2]]


Flatten makes this:

[course, course2, course3, course, course2]


Group_by turns it into:

{course =&gt; [course, course], course2 =&gt; [course2, course2], course3 =&gt; [course3]}


Map does:

[[course, 2], [course2, 2] , [course3, 1]]


Then to_h:

{course =&gt; 2, course2 =&gt; 2, course3 =&gt; 1}


At that point you can access the course hash and get the number.

course_hash[course]
# 2


Now that we have the hash we can update the needed column in Course:

Course.find_each do |course|
  course.update_attributes(needed: course_hash[course].to_i)
end


The to_i is used so that if course_hash does not contain the course it returns nil, then to_i will turn nil into 0.