Skip to content

Instantly share code, notes, and snippets.

@Jamedjo
Forked from rsutphin/exceed_query_limit.rb
Last active January 16, 2024 13:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jamedjo/1c821dcef609902bac2a to your computer and use it in GitHub Desktop.
Save Jamedjo/1c821dcef609902bac2a to your computer and use it in GitHub Desktop.
RSpec::Matchers.define :exceed_query_limit do |expected|
supports_block_expectations
match do |block|
query_count(&block) > expected
end
failure_message_when_negated do |actual|
"Expected a maximum of #{expected} queries, got #{@recorder.count}:\n\n#{@recorder.log_message}"
end
def query_count(&block)
@recorder = ActiveRecord::QueryRecorder.new(&block)
@recorder.count
end
end
module ActiveRecord
class QueryRecorder
attr_reader :log
def initialize(&block)
@log = []
ActiveSupport::Notifications.subscribed(method(:callback), 'sql.active_record', &block)
end
def callback(name, start, finish, message_id, values)
return if %w(CACHE SCHEMA).include?(values[:name])
@log << values[:sql]
end
def count
@log.count
end
def log_message
@log.join("\n\n")
end
end
end
def non_rspec_test
query_record = ActiveRecord::QueryRecorder.new{ model.some_method }
assert(query_record.count < 3, query_record.log_message)
end
it "doesn't need excessive database calls" do
expect{ booking.status_hash }.not_to exceed_query_limit(3)
end
# Alternative usage with control count
it 'avoids excessive database calls' do
control_count = ActiveRecord::QueryRecorder.new{ booking.status_hash }.count
create_list(:booking, 10)
expect{ booking.status_hash }.not_to exceed_query_limit(control_count)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment