How to prevent n + 1 queries using Rspec with the usage of ActiveSupport::Notifications.subscribed

How to prevent n + 1 queries using Rspec with the usage of ActiveSupport::Notifications.subscribed

I have seen many times that I forget to lazy load associations when doing queries and that generates n + 1 queries, in order to avoid and reduce these errors most of the time I add some scenarios in rspec that prevents `n + 1 queries` using a simple helper in rspec:

spec/support/query_limit.rb

module Common
  module Helpers
    def print_queries_generated_for &block
      counter_f = ->(name, started, finished, unique_id, payload) {
        unless payload[:name].in? %w[ CACHE SCHEMA ]
          puts "====================================="
          puts payload
          puts "====================================="
        end
      }

      ActiveSupport::Notifications.subscribed(counter_f, "sql.active_record", &block)
    end

    def count_queries_for &block
      count = 0

      counter_f = ->(name, started, finished, unique_id, payload) {
        unless payload[:name].in? %w[ CACHE SCHEMA ]
          count += 1
        end
      }

      ActiveSupport::Notifications.subscribed(counter_f, "sql.active_record", &block)

      count
    end
  end
end

spec/rails_helper.rb or spec/spec_helper.rb

config.include Common::Helpers

Usage:

it 'does not make a n + 1 queries' do
  result = count_queries_for do
    get :index, { format: :json, version: 1 }
  end

  expect(result).to eq(1)
end

or

it 'does not make a n + 1 queries' do
  result = count_queries_for do
    SurveyRespondent.count
  end

  expect(result).to eq(1)
end

If you want to see the output of the queries involved in that scope or endpoint use the method:

print_queries_generated_for do
  get :index, { format: :json, version: 1 }
end

That’s it

No Comments

Post A Comment