ar-query-matchers 0.7.0 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e73f1af783ac0aea8a1342b20e01d139106e29c2c4048bf3d30086a13675f204
4
- data.tar.gz: 64b309608ae8f52ba8d7a998ea0e7658eebb2ee7d11122d8e1c0934f042131b6
3
+ metadata.gz: 2bbbb0ab94d0e842a364dbe7d970900fa6bcdf2b6d9d3a0a2eb3cfac96df9efd
4
+ data.tar.gz: 6650c24207bd4a7d47077ec311b05530eab74dca5b097537ca554023f8cd92ce
5
5
  SHA512:
6
- metadata.gz: 13b5fe44e89c7e0df944882d4d15dac2ff72b8fe3a679591c46b15015587159246c4e2344d2e604b6a31a0ee6dc5a450eacd85ef638d90d578f1b4073fca2f58
7
- data.tar.gz: 61d48528375466023a71bf17ad2e453ec62ce5520f43200f88de94ff2f116522be3694fe2c0116f83093fa5f1087cf4774471143e63deb8f465dd03173bda8cd
6
+ metadata.gz: 1b548ed7b6d0d3ad9d144f2994846c84e087c420f5390cfe2ad957b3a598383c07576d5d51e5cb209bc589e928ad92fd7af56c1c40c73b198d510dab0721c50e
7
+ data.tar.gz: e27df0c699c8c2021d0e146f6070cba820226e2ca4dcc2258bcde3247356b4007600433cf928da00bda8585d1a32e8c638097ec95ecfa2e524db5e1194c4a5b4
data/CHANGELOG.md CHANGED
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.8.0] - 2022-01-27
10
+ ### Added
11
+ - Changed the implementation of ArQueryMatchers::Queries::TableName to calculate distance of class name to table name to determine which class name is most likely. This changes how tables in `only_load_at_most_models` are calculated.
12
+
9
13
  ## [0.7.0] - 2022-01-27
10
14
  ### Added
11
15
  - 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.
data/README.md CHANGED
@@ -16,7 +16,7 @@ If you'd like to pick that up, please have a look at: https://github.com/Gusto/a
16
16
  Include it in your Gemfile:
17
17
  ```ruby
18
18
  group :test do
19
- gem 'ar-query-matchers', '~> 0.2.0', require: false
19
+ gem 'ar-query-matchers', '~> 0.7.0', require: false
20
20
  end
21
21
  ```
22
22
 
@@ -40,9 +40,10 @@ This gem defines a few categories of matchers:
40
40
  - **Update**: Which models are updated during a block
41
41
 
42
42
  Each matcher category includes 3 assertions, for example, for the Load category, you could use the following assertions:
43
- - **only_load_models**: Strict assertion, not other query is allowed.
43
+ - **only_load_models**: Strict assertion of both models loaded and query counts. No other query is allowed.
44
+ - **only_load_at_most_models**: Strict assertion of models loaded, with an upper bound on the number of queries allowed against each.
44
45
  - **not_load_models**: No models are allowed to be loaded.
45
- - **load_models**: Inclusion, other models are allowed to be loaded if not specified in the assertion.
46
+ - **load_models**: Inclusion. Other models are allowed to be loaded if not specified in the assertion.
46
47
 
47
48
 
48
49
  **For example:**
@@ -58,6 +59,17 @@ expect { some_code() }.to only_load_models(
58
59
  )
59
60
  ```
60
61
 
62
+ The following spec will pass only if there are 4 or less SQL SELECTs that
63
+ load User records (and 1 or less for both Address and Payroll respectively) _and_ no other models
64
+ perform any SELECT queries.
65
+ ```ruby
66
+ expect { some_code() }.to only_load_at_most_models(
67
+ 'User' => 4,
68
+ 'Address' => 1,
69
+ 'Payroll' => 1,
70
+ )
71
+ ```
72
+
61
73
  The following spec will pass only if there are no select queries.
62
74
  ```ruby
63
75
  expect { some_code() }.to not_load_models
@@ -17,7 +17,7 @@ module ArQueryMatchers
17
17
  class CreateQueryFilter < QueryFilter
18
18
  # Matches unnamed SQL operations like the following:
19
19
  # "INSERT INTO `company_approval_details` ..."
20
- TABLE_NAME_SQL_PATTERN = /INSERT INTO [`"](?<table_name>[^`"]+)[`"]/.freeze
20
+ TABLE_NAME_SQL_PATTERN = /INSERT INTO [`"](?<table_name>[^`"]+)[`"]/
21
21
 
22
22
  def filter_map(_name, sql)
23
23
  # for inserts, name is always 'SQL', we have to rely on pattern matching the query string.
@@ -17,11 +17,11 @@ module ArQueryMatchers
17
17
  class LoadQueryFilter < Queries::QueryFilter
18
18
  # Matches named SQL operations like the following:
19
19
  # 'User Load'
20
- MODEL_LOAD_PATTERN = /\A(?<model_name>[\w:]+) (Load|Exists)\Z/.freeze
20
+ MODEL_LOAD_PATTERN = /\A(?<model_name>[\w:]+) (Load|Exists)\Z/
21
21
 
22
22
  # Matches unnamed SQL operations like the following:
23
23
  # "SELECT COUNT(*) FROM `users` ..."
24
- MODEL_SQL_PATTERN = /SELECT (?:(?!SELECT).)* FROM [`"](?<table_name>[^`"]+)[`"]/.freeze
24
+ MODEL_SQL_PATTERN = /SELECT (?:(?!SELECT).)* FROM [`"](?<table_name>[^`"]+)[`"]/
25
25
 
26
26
  def filter_map(name, sql)
27
27
  # First check for a `SELECT * FROM` query that ActiveRecord has
@@ -71,7 +71,7 @@ module ArQueryMatchers
71
71
 
72
72
  # The 'marginalia' gem adds a line from the backtrace to the SQL query in
73
73
  # the form of a comment.
74
- MARGINALIA_SQL_COMMENT_PATTERN = %r{/*line:(?<line>.*)'*/}.freeze
74
+ MARGINALIA_SQL_COMMENT_PATTERN = %r{/*line:(?<line>.*)'*/}
75
75
  private_constant :MARGINALIA_SQL_COMMENT_PATTERN
76
76
 
77
77
  def to_proc(queries)
@@ -31,9 +31,9 @@ module ArQueryMatchers
31
31
  # { 'users' => [User, AtoUser],
32
32
  # 'employees => [Employee, PandaFlows::StateFields] }
33
33
 
34
- # Of all the models that share the same table name sort them by their
35
- # relative ancestry and pick the one that all the rest inherit from
36
- tables[table_name].min_by { |a, b| a.ancestors.include?(b) }
34
+ # Pick the class with the shortest distance to the table name
35
+ ideal_class_name = table_name.classify
36
+ tables[table_name].min_by { |a| DidYouMean::Levenshtein.distance(ideal_class_name, a.to_s) }
37
37
  end
38
38
  end
39
39
  end
@@ -17,7 +17,7 @@ module ArQueryMatchers
17
17
  class UpdateQueryFilter < QueryFilter
18
18
  # Matches unnamed SQL operations like the following:
19
19
  # "UPDATE `bank_account_verifications` ..."
20
- TABLE_NAME_SQL_PATTERN = /UPDATE [`"](?<table_name>[^`"]+)[`"]/.freeze
20
+ TABLE_NAME_SQL_PATTERN = /UPDATE [`"](?<table_name>[^`"]+)[`"]/
21
21
 
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.
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.7.0
4
+ version: 0.8.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: 2022-01-28 00:00:00.000000000 Z
11
+ date: 2023-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -192,7 +192,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
192
192
  - !ruby/object:Gem::Version
193
193
  version: '0'
194
194
  requirements: []
195
- rubygems_version: 3.0.3.1
195
+ rubygems_version: 3.4.10
196
196
  signing_key:
197
197
  specification_version: 4
198
198
  summary: Ruby test matchers for instrumenting ActiveRecord query counts