mensa 0.7.1 → 0.7.3

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: c9016fbd279d8168641f18891986045e07f26b124842610e22728268d3f7557e
4
- data.tar.gz: 9ca2ab7decb8b7a5d901821a3d129c94ae3a43f20bd981c1d7cb1d0ab68cb402
3
+ metadata.gz: 9bf52a653e507bed6b1fe67a162dfa882b8dab27aa377b3d883e3da45f67f727
4
+ data.tar.gz: da0c8e7b5c349f4f5bd8c4358797a5eec1327ecf1171dc6de7158b0cc9cfbee4
5
5
  SHA512:
6
- metadata.gz: dbcd2b404c1da8e152ac4ad555a3a95093a0a33bafb3f809f9f099c2b21b21028667b2dae708ffae57dcd9d0e9db2fd539de2baea1110e0628d536b01d9aab49
7
- data.tar.gz: 49e1a2b30f5efd72d913d22981aad389116d3935dedd4245ffebbc87637222a1f3bca58850bbbd094461b59b29bce9400e9a94867608195d96fc2ecf4773313b
6
+ metadata.gz: 0c9e920e4760b45ea4d3ecb2f4e09745a84bc1830e70a3a2085fba4b5511411df65b607fecc9e11ec827811a71848d8a4f66c1be7f0a71b61a77d4100b3b5c99
7
+ data.tar.gz: b86ee152657699c2739acda33e9b24afcd04e2360a2f034c2d20b27bb2aaa7d5ba53b1677ea0cef76fa238e179c05eec5194fc268069a1c0fda06d7a761ac10e
data/.shipkit.yml CHANGED
@@ -1,2 +1,2 @@
1
1
  ---
2
- previous_version: 0.7.0
2
+ previous_version: 0.7.2
data/CHANGELOG.md CHANGED
@@ -1,10 +1,21 @@
1
1
  # Changelog
2
2
 
3
- ## Unreleased
3
+ ## 0.7.3
4
+
5
+ - **Behaviour change:** the `matches` and `does_not_match` filters now do a
6
+ case-insensitive "contains" (`ILIKE '%value%'`), the same way search does.
7
+ Before, they passed the value to `LIKE` as it was, so `matches "LLC"` only
8
+ found rows that were exactly `LLC`. The value is taken literally, so saved
9
+ views that relied on typing `%` or `_` wildcards now match a literal `%` or
10
+ `_`. `does_not_match` now also returns rows where the column is NULL.
11
+ Attributes without a `type` are cast to text for the comparison.
12
+
13
+ ## 0.7.2
4
14
 
5
15
  - The verifier's report only lists failures and warnings. `-v`/`--verbose` (or
6
16
  `VERBOSE=1`) on the rake tasks, or `result.to_s(verbose: true)`, lists every
7
- check.
17
+ check, and the classes in `app/tables` that were skipped as they aren't Mensa
18
+ tables.
8
19
 
9
20
  ## 0.7.0
10
21
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mensa (0.7.0)
4
+ mensa (0.7.2)
5
5
  csv
6
6
  importmap-rails
7
7
  pagy (>= 43)
data/README.md CHANGED
@@ -187,6 +187,11 @@ The operators are `is`, `isnt`, `matches`, `does_not_match`, `gt`, `gteq`, `lt`,
187
187
  | boolean, uuid, enums and other types | `is`, `isnt` |
188
188
  | jsonb, json | none (json also has no `is_duplicate`) |
189
189
 
190
+ `matches` finds rows where the column contains the value anywhere, ignoring case
191
+ (`ILIKE '%value%'`), and `does_not_match` finds the others, including rows where the
192
+ column is empty (NULL). The value is taken literally: `%`, `_` and `\` are matched as
193
+ characters, not as wildcards. A blank value matches only empty strings.
194
+
190
195
  `matches` and `does_not_match` are left out when the filter has a `collection`, and
191
196
  `is_current` is only offered when `Current` has a method named after the column.
192
197
 
@@ -458,7 +463,7 @@ bin/rails "mensa:verify[inventories]" -v
458
463
  ```
459
464
 
460
465
  Classes and modules that don't descend from `Mensa::Base` (e.g. helpers in
461
- `app/tables`) are reported as skipped.
466
+ `app/tables`) are skipped, and only reported as such with `-v`.
462
467
 
463
468
  #### From tests
464
469
 
@@ -14,7 +14,7 @@ module Mensa
14
14
  config_reader :multiple
15
15
  config_reader :having?
16
16
 
17
- # Types that LIKE works on, nil is an attribute without a type
17
+ # Types that ILIKE works on, nil is an attribute without a type
18
18
  TEXT_TYPES = [:string, :text, :citext, nil].freeze
19
19
  # Types with a meaningful order, for gt, gteq, lt and lteq
20
20
  RANGE_TYPES = %i[integer bigint float decimal money date datetime timestamp timestamptz time interval].freeze
@@ -139,9 +139,12 @@ module Mensa
139
139
  hash[:value] = Current.public_send(column.name)
140
140
  "#{col} = :value"
141
141
  when :matches
142
- "#{col} LIKE :value"
142
+ hash[:value] = contains_pattern(hash[:value])
143
+ "#{text_col(col)} ILIKE :value"
143
144
  when :does_not_match
144
- "#{col} NOT LIKE :value"
145
+ # Rows without a value don't contain it either
146
+ hash[:value] = contains_pattern(hash[:value])
147
+ "(#{col} IS NULL OR #{text_col(col)} NOT ILIKE :value)"
145
148
  when :is
146
149
  hash[:value].is_a?(Array) ? "#{col} IN (:value)" : "#{col} = :value"
147
150
  when :isnt
@@ -280,6 +283,23 @@ module Mensa
280
283
  record_scope.having("#{column_sql} IN (#{duplicate_values_scope.to_sql})")
281
284
  end
282
285
 
286
+ # A case-insensitive "contains" pattern, with %, _ and \ in the value
287
+ # matched literally. A blank value is compared as it is, like `is` does,
288
+ # so it doesn't turn into '%%' and match everything.
289
+ def contains_pattern(value)
290
+ return value if value.to_s.empty?
291
+
292
+ "%#{ActiveRecord::Base.sanitize_sql_like(value.to_s)}%"
293
+ end
294
+
295
+ # An attribute without a type may not be text in SQL (e.g. a count), cast
296
+ # it like search does. Typed columns are compared as they are, so an
297
+ # explicit `matches` on e.g. a boolean still fails (and the verifier
298
+ # reports it).
299
+ def text_col(col)
300
+ column.type.nil? ? "CAST(#{col} AS text)" : col
301
+ end
302
+
283
303
  # Unused at the moment
284
304
  def normalize(query)
285
305
  query
@@ -95,21 +95,23 @@ module Mensa
95
95
  # Context comes from USER_ID, ACCOUNT_ID and PARAMS (JSON) in +env+, and
96
96
  # STRICT=1 makes warnings fail, used by the mensa:verify rake tasks.
97
97
  # The reports list failures and warnings, +verbose+ (or VERBOSE=1) lists
98
- # every check.
98
+ # every check and the classes skipped as they aren't Mensa tables.
99
99
  def run(tables = nil, env: ENV, io: $stdout, verbose: false)
100
100
  classes = tables.present? ? Array(tables).map { |table| resolve_table_class(table) } : table_classes
101
101
  options = options_from_env(env)
102
102
  verbose ||= %w[1 true yes].include?(env["VERBOSE"].to_s.downcase)
103
103
 
104
104
  results = classes.flat_map do |klass|
105
- verify(klass, **options).each { |result| io.puts(result.to_s(verbose: verbose), "") }
105
+ verify(klass, **options).each do |result|
106
+ io.puts(result.to_s(verbose: verbose), "") if verbose || result.mensa_table?
107
+ end
106
108
  end
107
109
 
108
110
  by_table = results.select(&:mensa_table?).group_by(&:table_class)
109
111
  others = results.reject(&:mensa_table?)
110
- if results.size > 1
112
+ if by_table.size > 1 || (verbose && results.size > 1)
111
113
  passed = by_table.count { |_table, table_results| table_results.all?(&:success?) }
112
- io.puts ["#{passed}/#{by_table.size} tables passed", ("#{others.size} skipped, not a Mensa::Base subclass" if others.any?)].compact.join(", ")
114
+ io.puts ["#{passed}/#{by_table.size} tables passed", ("#{others.size} skipped, not a Mensa::Base subclass" if verbose && others.any?)].compact.join(", ")
113
115
  end
114
116
  results.all?(&:success?)
115
117
  end
data/lib/mensa/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mensa
2
- VERSION = "0.7.1"
2
+ VERSION = "0.7.3"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mensa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.7.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom de Grunt