DEV Community

Lazy coder
Lazy coder

Posted on

N+1 in Ruby on Rails

How to detect N+1

Prosopite

Install

gem install prosopite
Enter fullscreen mode Exit fullscreen mode
bundle add prosopite
Enter fullscreen mode Exit fullscreen mode
# Gemfile
gem 'prosopite'
Enter fullscreen mode Exit fullscreen mode

Configure

Controller
Add the following to ApplicationController

class ApplicationController < ActionController::Base
  unless Rails.env.production?
    before_action do
      Prosopite.scan
    end

    after_action do
      Prosopite.finish
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

Enable logging

# config/environments/development.rb

config.after_initialize do
  Prosopite.rails_logger = true
end
Enter fullscreen mode Exit fullscreen mode

Spec

# config/environments/test.rb

config.after_initialize do
  Prosopite.rails_logger = true
  Prosopite.raise = true
end
Enter fullscreen mode Exit fullscreen mode
# spec/spec_helper.rb

config.before do
  Prosopite.scan
end

config.after do
  Prosopite.finish
end
Enter fullscreen mode Exit fullscreen mode

Now everytime you run the test, you will be able to see any error about N+1 queries.

Note: It won't raise any exception if only one association.

For example

class Teacher < ActiveRecord
  has_many :students
end
Enter fullscreen mode Exit fullscreen mode
class Student < ActiveRecord
  belongs_to :teacher
end
Enter fullscreen mode Exit fullscreen mode

No exception

teacher = Teacher.create(name: 'John')
teacher.students.create(name: 'Tom')

Teacher.first.students do |student|
  puts student.name
end
Enter fullscreen mode Exit fullscreen mode

Throw exception about N+1

teacher = Teacher.create(name: 'John')
teacher.students.create(name: 'Tom')
teacher.students.create(name: 'Jerry')

Teacher.first.students do |student|
  puts student.name
end
Enter fullscreen mode Exit fullscreen mode
Prosopite::NPlusOneQueriesError:
       N+1 queries detected:
         SELECT `students`.* FROM `students` WHERE `students`.`id` = ? LIMIT ?

Enter fullscreen mode Exit fullscreen mode

Top comments (0)