NOne CI

NOne is able to auto-detect N+1 queries with confidence

Note! It is a rewrite of similar library https://github.com/charkost/prosopite. All credits go there.

How it works

NOne monitors all SQL queries using the Active Support instrumentation and looks for the following pattern which is present in all N+1 query cases:

More than one queries have the same call stack and the same query fingerprint.

Installation

Add this line to your application's Gemfile:

gem 'pg_query'
gem 'n_one'

And then execute:

$ bundle install

Or install it yourself as:

$ gem install n_one

Development Environment Usage

NOne auto-detection can be enabled on all controllers:

class ApplicationController < ActionController::Base
  unless Rails.env.production?
    around_action do
      NOne.scan! do
        yield
      end
    end
  end
end

Test Environment Usage

And each test can be scanned with:

# spec/spec_helper.rb
config.around(:each) do |example|
  NOne.scan! do
    example.run
  end
end

or with custom code using scan report

# spec/your_spec.rb
it 'has no N+1 queries' do
  n_ones = NOne.scan do
    MyAction.perform(arguments)
  end

  expect(n_ones.size).to eq(0)
end

Whitelisting

Ignore notifications for call stacks containing one or more substrings:

NOne.scan!(whitelist: ['myapp/lib/known_n_plus_ones/']) do
  example.run
end

Ignore names

Ignore queries with names:

NOne.scan!(ignore_names: ['SCHEMA']) do
  example.run
end

It will skip schema queries(e.g. for column names of a given table)

Stack trace sanitizing

Sanitize the call stack trace that is used to calculate the query fingerprint:

sanitizer = lambda do |stacktrace|
  stacktrace.reject { |s| s.include?('/active_record/relation/delegation.rb') }
end

NOne.scan!(stacktrace_sanitizer: sanitizer) do
  example.run
end

Consider the following example:

class Foo < ActiveRecord::Base
  def self.bar
    first(5)
  end
end

2.times { Foo.all.bar }

The subsequent Foo.all.bar call here will not be recognized as an N+1 query since it will have a different call stack trace (see the reason here). This can be fixed with the stacktrace_sanitizer option as described above.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/prikha/n_one.

License

NOne is licensed under the Apache License, Version 2.0. See LICENSE.txt for the full license text.