Last active
June 20, 2019 10:23
-
-
Save nbulaj/6d6c2af5955503d9fd7b4a6702dcf564 to your computer and use it in GitHub Desktop.
This file contains 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
# frozen_string_literal: true | |
RSpec::Matchers.define :exceed_query_limit do |expected, pattern = nil| | |
supports_block_expectations | |
match do |block| | |
query_count(pattern, &block) > expected | |
end | |
failure_message_when_negated do |actual| | |
"Expected to run maximum #{expected} queries, got #{@counter.query_count}" | |
end | |
def query_count(pattern, &block) | |
@counter = ActiveRecord::QueryCounter.new(pattern) | |
ActiveSupport::Notifications.subscribed(@counter.to_proc, 'sql.active_record', &block) | |
@counter.query_count | |
end | |
end |
This file contains 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
# frozen_string_literal: true | |
# spec/support/active_record_query_counter.rb | |
module ActiveRecord | |
class QueryCounter | |
IGNORED_SQL = [ | |
/^PRAGMA (?!(table_info))/, | |
/^SELECT currval/, | |
/^SELECT CAST/, | |
/^SELECT @@IDENTITY/, | |
/^SELECT @@ROWCOUNT/, | |
/^SAVEPOINT/, | |
/^ROLLBACK TO SAVEPOINT/, | |
/^RELEASE SAVEPOINT/, | |
/^SHOW max_identifier_length/, | |
].freeze | |
attr_reader :pattern, :queries_count | |
def initialize(pattern) | |
@pattern = pattern | |
@queries_count = 0 | |
end | |
def to_proc | |
lambda(&method(:callback)) | |
end | |
def callback(_name, _start, _finish, _message_id, values) | |
@queries_count += 1 if !ignore?(values) && match_pattern?(values) | |
end | |
def ignore?(values) | |
%w[CACHE SCHEMA].include?(values[:name]) || | |
IGNORED_SQL.any? { |query| values[:sql] =~ query } | |
end | |
def match_pattern?(values) | |
return true if @pattern.nil? | |
values[:sql] =~ @pattern | |
end | |
end | |
end |
This file contains 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
it "checks for N+1 on querying" do | |
# .with_some_associations must perform includes with JOIN and perform only one SELECT query | |
expect { SomeModel.with_some_associations.first }.not_to exceed_query_limit(1) | |
end | |
it "checks count of UPDATE statements" do | |
# just an example | |
expect { MySyperRepository.create_invocve!}.not_to exceed_query_limit(2, /^UPDATE/) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment