2

My rails application took so long time to render the view. This view has consisted of child objects.

First of all, My 'course' object belong to 'school'

class Course < ApplicationRecord
    belongs_to :school
end
class School < ApplicationRecord
    has_many :courses, dependent: :destroy 
end

and Controller.

class CoursesController < ApplicationController
    before_action :set_course , only: [:show, :edit, :update, :destroy]

    # GET /courses
    # GET /courses.json
    def index
       @courses = Course.all
    end

   // other stuffs..

end

In a View, I have a part for rendering the course's relation with a school in DB.

index.html.erb

<div>
    <table>
        <thead>
            //.....stuffss..
        </thead>
        <tbody>

            <% @courses.each do |course| %>
            <tr>
                <th><%= course.school.location %></th> // This parts are referencing 'school'..
                <td><%= course.school.name %></td>
                <td><%= course.name %></td>
                <td><%= convert_currency(course.price) %></td>
                <td><%= link_to "course", course_path(course.id), :class => 'button'  %></td>
                <td><%= course.school.nationalmix %></td>
                <td><%= course.school.certificate %></td>
                <td><%= course.school.good %></td>
                <td><%= course.school.bad %></td>
                <td><%= link_to "course", course_path(course.id), :class => 'button'  %> </td>
            </tr>
            <% end %>

        </tbody>
    </table>
</div>

It turned out that rendering page is taking so long time.

Started GET "/courses" for ::1 at 2019-11-21 10:57:23 +0000
Processing by CoursesController#index as HTML
  Rendering courses/index.html.erb within layouts/application
  Course Load (0.3ms)  SELECT "courses".* FROM "courses"
  ↳ app/views/courses/index.html.erb:102
  School Load (0.2ms)  SELECT "schools".* FROM "schools" WHERE "schools"."id" = $1 LIMIT $2  [["id", 4], ["LIMIT", 1]]
  ↳ app/views/courses/index.html.erb:104
  School Load (0.2ms)  SELECT "schools".* FROM "schools" WHERE "schools"."id" = $1 LIMIT $2  [["id", 5], ["LIMIT", 1]]
  ↳ app/views/courses/index.html.erb:104
  School Load (0.4ms)  SELECT "schools".* FROM "schools" WHERE "schools"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳ app/views/courses/index.html.erb:104
  CACHE School Load (0.0ms)  SELECT "schools".* FROM "schools" WHERE "schools"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳ app/views/courses/index.html.erb:104
  School Load (0.3ms)  SELECT "schools".* FROM "schools" WHERE "schools"."id" = $1 LIMIT $2  [["id", 2], ["LIMIT", 1]]
  ↳ app/views/courses/index.html.erb:104
  Rendered courses/index.html.erb within layouts/application (Duration: 7941.3ms | Allocations: 184810) // See this line.
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 6], ["LIMIT", 1]]
  ↳ app/views/layouts/application.html.erb:71
Completed 200 OK in 8015ms (Views: 8011.2ms | ActiveRecord: 1.8ms | Allocations: 205787)

Rendered courses/index.html.erb within layouts/application (Duration: 7941.3ms | Allocations: 184810)

Almost 8 seconds. Is there any better way of doing this?

mrzasa
  • 22,895
  • 11
  • 56
  • 94
Jin Lim
  • 1,759
  • 20
  • 24

1 Answers1

4

You need to load schools eagerly:

@courses = Course.all.includes(:school)

Very detailed description you can find in this excellent blog post

mrzasa
  • 22,895
  • 11
  • 56
  • 94
  • I applied this and other recommendations in the blog post. but it didn't improve the performances. – Jin Lim Nov 21 '19 at 11:48
  • Do you still have multiple SQL statements for loading schools in your logs? – mrzasa Nov 21 '19 at 11:51
  • Maybe you should paginate the results, instead of showing all of them on a single page? How many courses d you have? – mrzasa Nov 21 '19 at 11:52
  • I can see only 1 SQL statement. yes true. and I also assume that `convert_currency(course.price)` this making API call which caused the issue mainly. – Jin Lim Nov 21 '19 at 12:15
  • Yes, It was the problem. and I solved it with Rails Caching. and Thanks for the eager_loading method. That obviously helped performance somehow. https://stackoverflow.com/a/30111615/4735043 – Jin Lim Nov 21 '19 at 16:56