ar-query-matchers 0.5.2.pre.6 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -2
- data/lib/ar_query_matchers/queries/create_counter.rb +1 -1
- data/lib/ar_query_matchers/queries/load_counter.rb +14 -5
- data/lib/ar_query_matchers/queries/query_counter.rb +2 -6
- data/lib/ar_query_matchers/queries/update_counter.rb +1 -1
- data/lib/ar_query_matchers.rb +43 -0
- metadata +18 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e73f1af783ac0aea8a1342b20e01d139106e29c2c4048bf3d30086a13675f204
|
4
|
+
data.tar.gz: 64b309608ae8f52ba8d7a998ea0e7658eebb2ee7d11122d8e1c0934f042131b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 13b5fe44e89c7e0df944882d4d15dac2ff72b8fe3a679591c46b15015587159246c4e2344d2e604b6a31a0ee6dc5a450eacd85ef638d90d578f1b4073fca2f58
|
7
|
+
data.tar.gz: 61d48528375466023a71bf17ad2e453ec62ce5520f43200f88de94ff2f116522be3694fe2c0116f83093fa5f1087cf4774471143e63deb8f465dd03173bda8cd
|
data/CHANGELOG.md
CHANGED
@@ -6,9 +6,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
-
## [0.
|
9
|
+
## [0.7.0] - 2022-01-27
|
10
|
+
### Added
|
11
|
+
- A new matcher, `only_load_at_most_models`, will do a less-than-or-equal-to (<=) check on model counts. This is a method that makes tests less noisy as performance gets better.
|
12
|
+
|
13
|
+
## [0.6.0] - 2022-01-05
|
14
|
+
### Changed
|
15
|
+
- Support Rails 7
|
16
|
+
|
17
|
+
## [0.5.3] - 2021-05-26
|
18
|
+
### Changed
|
19
|
+
- Re-release of previous version due to accidental premature release
|
20
|
+
|
21
|
+
## [0.5.2] - 2021-05-26
|
10
22
|
### Changed
|
11
|
-
-
|
23
|
+
- Update MODEL_SQL_PATTERN to allow for more accurate matches against SQL strings
|
12
24
|
|
13
25
|
## [0.5.1] - 2020-11-19
|
14
26
|
### Changed
|
@@ -23,7 +23,7 @@ module ArQueryMatchers
|
|
23
23
|
# for inserts, name is always 'SQL', we have to rely on pattern matching the query string.
|
24
24
|
select_from_table = sql.match(TABLE_NAME_SQL_PATTERN)
|
25
25
|
|
26
|
-
|
26
|
+
TableName.new(select_from_table[:table_name]) if select_from_table
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -15,15 +15,24 @@ module ArQueryMatchers
|
|
15
15
|
end
|
16
16
|
|
17
17
|
class LoadQueryFilter < Queries::QueryFilter
|
18
|
+
# Matches named SQL operations like the following:
|
19
|
+
# 'User Load'
|
20
|
+
MODEL_LOAD_PATTERN = /\A(?<model_name>[\w:]+) (Load|Exists)\Z/.freeze
|
21
|
+
|
18
22
|
# Matches unnamed SQL operations like the following:
|
19
|
-
# "SELECT * FROM `users` ..."
|
23
|
+
# "SELECT COUNT(*) FROM `users` ..."
|
20
24
|
MODEL_SQL_PATTERN = /SELECT (?:(?!SELECT).)* FROM [`"](?<table_name>[^`"]+)[`"]/.freeze
|
21
25
|
|
22
|
-
def filter_map(
|
23
|
-
#
|
26
|
+
def filter_map(name, sql)
|
27
|
+
# First check for a `SELECT * FROM` query that ActiveRecord has
|
28
|
+
# helpfully named for us in the payload
|
29
|
+
match = name.match(MODEL_LOAD_PATTERN)
|
30
|
+
return ModelName.new(match[:model_name]) if match
|
31
|
+
|
32
|
+
# Fall back to pattern-matching on the table name in a COUNT and looking
|
24
33
|
# up the table name from ActiveRecord's loaded descendants.
|
25
|
-
|
26
|
-
|
34
|
+
select_from_table = sql.match(MODEL_SQL_PATTERN)
|
35
|
+
TableName.new(select_from_table[:table_name]) if select_from_table
|
27
36
|
end
|
28
37
|
end
|
29
38
|
end
|
@@ -81,13 +81,9 @@ module ArQueryMatchers
|
|
81
81
|
# Given a `sql.active_record` event, figure out which model is being
|
82
82
|
# accessed. Some of the simpler queries have a :name key that makes this
|
83
83
|
# really easy. Others require parsing the SQL by hand.
|
84
|
-
|
85
|
-
|
86
|
-
# Round to microseconds
|
87
|
-
results&.each do |result|
|
88
|
-
model_name = result.model_name
|
89
|
-
next unless model_name
|
84
|
+
model_name = @query_filter.filter_map(payload[:name] || '', payload[:sql] || '')&.model_name
|
90
85
|
|
86
|
+
if model_name
|
91
87
|
comment = payload[:sql].match(MARGINALIA_SQL_COMMENT_PATTERN)
|
92
88
|
queries[model_name][:lines] << comment[:line] if comment
|
93
89
|
queries[model_name][:count] += 1
|
@@ -22,7 +22,7 @@ module ArQueryMatchers
|
|
22
22
|
def filter_map(_name, sql)
|
23
23
|
# for updates, name is always 'SQL', we have to rely on pattern matching on the query string instead.
|
24
24
|
select_from_table = sql.match(TABLE_NAME_SQL_PATTERN)
|
25
|
-
|
25
|
+
TableName.new(select_from_table[:table_name]) if select_from_table
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
data/lib/ar_query_matchers.rb
CHANGED
@@ -97,6 +97,49 @@ module ArQueryMatchers
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
100
|
+
# The following will fail because the call to `User` is not expected, even
|
101
|
+
# though the Payroll count is correct:
|
102
|
+
#
|
103
|
+
# expect {
|
104
|
+
# Payroll.count
|
105
|
+
# Payroll.count
|
106
|
+
# User.count
|
107
|
+
# }.to only_load_at_most_models(
|
108
|
+
# 'Payroll' => 2,
|
109
|
+
# )
|
110
|
+
#
|
111
|
+
# The following will succeed because the counts are exact:
|
112
|
+
#
|
113
|
+
# expect {
|
114
|
+
# Payroll.count
|
115
|
+
# Payroll.count
|
116
|
+
# User.count
|
117
|
+
# }.to only_load_at_most_models(
|
118
|
+
# 'Payroll' => 2,
|
119
|
+
# 'User' => 1,
|
120
|
+
# )
|
121
|
+
#
|
122
|
+
RSpec::Matchers.define(:only_load_at_most_models) do |expected = {}|
|
123
|
+
include MatcherConfiguration
|
124
|
+
include MatcherErrors
|
125
|
+
|
126
|
+
match do |block|
|
127
|
+
@query_stats = Queries::LoadCounter.instrument(&block)
|
128
|
+
expected_queries = Utility.remove_superfluous_expectations(expected)
|
129
|
+
actual_queries = @query_stats.query_counts
|
130
|
+
|
131
|
+
all_models = expected_queries.keys | actual_queries.keys
|
132
|
+
|
133
|
+
all_models.each do |model|
|
134
|
+
expect(actual_queries[model] || 0).to be <= expected_queries[model]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def failure_text
|
139
|
+
expectation_failed_message('load at most')
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
100
143
|
RSpec::Matchers.define(:not_load_any_models) do
|
101
144
|
include MatcherConfiguration
|
102
145
|
include MatcherErrors
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ar-query-matchers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matan Zruya
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -17,9 +17,6 @@ dependencies:
|
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '4.0'
|
20
|
-
- - "<"
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '7.0'
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -27,9 +24,6 @@ dependencies:
|
|
27
24
|
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '4.0'
|
30
|
-
- - "<"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '7.0'
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: activesupport
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -37,9 +31,6 @@ dependencies:
|
|
37
31
|
- - ">="
|
38
32
|
- !ruby/object:Gem::Version
|
39
33
|
version: '4.0'
|
40
|
-
- - "<"
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
version: '7.0'
|
43
34
|
type: :runtime
|
44
35
|
prerelease: false
|
45
36
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -47,9 +38,6 @@ dependencies:
|
|
47
38
|
- - ">="
|
48
39
|
- !ruby/object:Gem::Version
|
49
40
|
version: '4.0'
|
50
|
-
- - "<"
|
51
|
-
- !ruby/object:Gem::Version
|
52
|
-
version: '7.0'
|
53
41
|
- !ruby/object:Gem::Dependency
|
54
42
|
name: rspec
|
55
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -92,6 +80,20 @@ dependencies:
|
|
92
80
|
- - ">="
|
93
81
|
- !ruby/object:Gem::Version
|
94
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: byebug
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
95
97
|
- !ruby/object:Gem::Dependency
|
96
98
|
name: rake
|
97
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -186,9 +188,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
186
188
|
version: '0'
|
187
189
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
188
190
|
requirements:
|
189
|
-
- - "
|
191
|
+
- - ">="
|
190
192
|
- !ruby/object:Gem::Version
|
191
|
-
version:
|
193
|
+
version: '0'
|
192
194
|
requirements: []
|
193
195
|
rubygems_version: 3.0.3.1
|
194
196
|
signing_key:
|