Created
April 13, 2023 20:47
-
-
Save Dania02525/149f120bb347c6233aa1bc28d2a7f8cf to your computer and use it in GitHub Desktop.
A custom rspec matcher to catch n+1 queries
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# use this matched to catch most n+1 queries in request specs by creating at least three records, then | |
# doing something like expect { subject }.to not_execute_n_plus_one | |
RSpec::Matchers.define :not_execute_n_plus_one do | |
match do |block| | |
@queries = [] | |
ActiveSupport::Notifications.subscribe 'sql.active_record' do |_, _, _, _, values| | |
next if %w(CACHE SCHEMA).include? values[:name] | |
next if values[:sql].start_with?("SAVEPOINT") | |
next if values[:sql].start_with?("RELEASE SAVEPOINT") | |
next if values[:sql].start_with?("INSERT INTO") | |
@queries << values[:sql] | |
end | |
block.call | |
@sqls = @queries.reduce({}) do |acc, q| | |
acc["\"#{q}\""] ||= 0 | |
acc["\"#{q}\""] += 1 | |
acc | |
end.select { |_k, v| v > 2 } | |
@sqls.empty? | |
end | |
supports_block_expectations | |
failure_message do |_actual| | |
sql_messages = @sqls.map do |k, v| | |
"#{k} (executed #{v} times)" | |
end | |
"The following n+1(s) queries were found: \n#{sql_messages.join("\n")}" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment