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)