data_checks 0.1.0 → 0.2.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: 76f3628c85ded9452a6825695726c6814153051c3345812f6e411f447b9114fb
4
- data.tar.gz: 04bca1e6301d41a901e73432ad98b062e508a40e0156fa8a803e0c3fdb765f2d
3
+ metadata.gz: 990db04b3558c8b10439aa6af136f5415cffcfdf368ddd886db4c0c18b707896
4
+ data.tar.gz: 7acf51bdf1f5dc5b537577359257e33b110f0b2c3eb554ad8959eb25052c75c4
5
5
  SHA512:
6
- metadata.gz: 2133d07d50f683647d055aaf877169dadbd62bde6cde8bab24ed785e660c99f844ff80c2be0cd2f3bfec30ec8fba9d902d3ca85ef8dd877f89b54bfd1580d59c
7
- data.tar.gz: 8c14320fbeaf09ca1a789f7c4232e5908849ede96b645b13a8f12a1922e07902f700a8c6ae36221d47f485d15a72be1f499789a58f4c0a62e4219ee94a65347c
6
+ metadata.gz: 337bc667143363ae190de87729e3fbf17b940ebdaa1cd7ee701ed8f83e80b8dda30eb7db0ebdccd81231587c297df9ac662bf1bac23b0fa3c37f2bf828e382a1
7
+ data.tar.gz: 0b00bc6ee4b76e30023a4da4d20e9c9afb5b5f0d91936cfb21f024be8773e06e78db513df6e3776540a53cce7e0188d5ae3a6e1d714442ee01772afa3282b9c4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  ## master (unreleased)
2
2
 
3
+ ## 0.2.0 (2023-11-09)
4
+
5
+ - Add `ensure_equal` check method
6
+
7
+ ```ruby
8
+ ensure_equal :featured_projects, to: 100 do
9
+ FeaturedProject.count
10
+ end
11
+ ```
12
+
13
+ ## 0.1.1 (2022-11-26)
14
+
15
+ - Do not prematurely load `ActiveRecord::Base`
16
+
17
+ See https://github.com/rails/rails/issues/46567 for details.
18
+
3
19
  ## 0.1.0 (2022-04-21)
4
20
 
5
21
  - First release
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  This gem provides a small DSL to check your data for inconsistencies and anomalies.
4
4
 
5
+ [![Build Status](https://github.com/fatkodima/data_checks/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/fatkodima/data_checks/actions/workflows/test.yml)
6
+
5
7
  ## Installation
6
8
 
7
9
  Add this line to your application's Gemfile:
@@ -23,7 +25,15 @@ You could also assume that your data will never get corrupted, and validations d
23
25
 
24
26
  This gem doesn't aim to replace those tools, but provides something else that could serve a close purpose: *ensure that you work with the data you expect*.
25
27
 
26
- This gem help you to schedule some verifications on your data and get alerts when something is unexpected.
28
+ This gem helps you to schedule some verifications on your data and get alerts when something is unexpected.
29
+
30
+ `data_checks` can help to catch:
31
+
32
+ * 🐛 **Bugs due to race conditions** (e.g. user accidentally double clicks a button to delete an email and ends up without emails due to a race condition bug in the app)
33
+ * 🐛 **Invalid persisted data**
34
+ * 🐛 **Unexpected changes in behavior and data** (e.g. too many (too less) of something is created/deleted/imported/enqueued/..., etc)
35
+
36
+ This idea is nicely presented at RailsConf: [RailsConf 2018: The Doctor Is In: Using checkups to find bugs in production by Ryan Laughlin](https://www.youtube.com/watch?v=gEAlhKaK2I4)
27
37
 
28
38
  ## Usage
29
39
 
@@ -37,8 +47,15 @@ For example, we expect every image attachment to have previews in 3 sizes. It is
37
47
 
38
48
  ```ruby
39
49
  DataChecks.configure do
50
+ ensure_no :users_without_emails, tag: "minutely" do
51
+ User.where.missing(:email_addresses)
52
+ end
53
+
40
54
  ensure_no :images_without_previews, tag: "hourly" do
41
- Attachment.images.joins(:previews).having("COUNT(*) < 3").group(:attachment_id)
55
+ Attachment.images
56
+ .left_joins(:previews)
57
+ .group(:attachment_id)
58
+ .having("COUNT(previews.id) < 3")
42
59
  end
43
60
 
44
61
  notifier :email,
@@ -116,6 +133,7 @@ end
116
133
  * `ensure_any` will check that the result of a given block is `> 0`
117
134
  * `ensure_more` will check that the result of a given block is `>` than a given number or that it contains more than a given number of items
118
135
  * `ensure_less` will check that the result of a given block is `<` than a given number or that it contains less than a given number of items
136
+ * `ensure_equal` will check that the result of a given block is `==` to the given number or that it contains a given number of items
119
137
 
120
138
  ```ruby
121
139
  ensure_no :images_without_previews do
@@ -26,6 +26,10 @@ module DataChecks
26
26
  add_check(EnsureLess, name, options, block)
27
27
  end
28
28
 
29
+ def ensure_equal(name, **options, &block)
30
+ add_check(EnsureEqual, name, options, block)
31
+ end
32
+
29
33
  def notifier(name, **options)
30
34
  name = name.to_s
31
35
 
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DataChecks
4
+ class EnsureEqual < Check
5
+ private
6
+ def handle_result(result)
7
+ expected = options.fetch(:to)
8
+ passing = true
9
+ count = 0
10
+
11
+ case result
12
+ when Numeric
13
+ if result != expected
14
+ passing = false
15
+ count = result
16
+ end
17
+ # In ActiveRecord <= 4.2 ActiveRecord::Relation is not an Enumerable!
18
+ when Enumerable, ActiveRecord::Relation
19
+ count = result.size
20
+ if count != expected
21
+ passing = false
22
+ entries = result
23
+ end
24
+ else
25
+ raise ArgumentError, "Unsupported result: '#{result.class.name}' for 'ensure_equal'"
26
+ end
27
+
28
+ CheckResult.new(check: self, passing: passing, count: count, entries: entries)
29
+ end
30
+ end
31
+ end
@@ -5,23 +5,17 @@ module DataChecks
5
5
  private
6
6
  def handle_result(result)
7
7
  expected = options.fetch(:than)
8
- passing = true
9
8
 
10
9
  case result
11
10
  when Numeric
12
11
  count = result
13
- if result >= expected
14
- passing = false
15
- end
16
12
  when Enumerable, ActiveRecord::Relation
17
- count = result.count
18
- if count >= expected
19
- passing = false
20
- end
13
+ count = result.size
21
14
  else
22
15
  raise ArgumentError, "Unsupported result: '#{result.class.name}' for 'ensure_less'"
23
16
  end
24
17
 
18
+ passing = count < expected
25
19
  CheckResult.new(check: self, passing: passing, count: count)
26
20
  end
27
21
  end
@@ -5,23 +5,17 @@ module DataChecks
5
5
  private
6
6
  def handle_result(result)
7
7
  expected = options.fetch(:than)
8
- passing = true
9
8
 
10
9
  case result
11
10
  when Numeric
12
11
  count = result
13
- if result <= expected
14
- passing = false
15
- end
16
12
  when Enumerable, ActiveRecord::Relation
17
- count = result.count
18
- if count <= expected
19
- passing = false
20
- end
13
+ count = result.size
21
14
  else
22
15
  raise ArgumentError, "Unsupported result: '#{result.class.name}' for 'ensure_more'"
23
16
  end
24
17
 
18
+ passing = count > expected
25
19
  CheckResult.new(check: self, passing: passing, count: count)
26
20
  end
27
21
  end
@@ -15,7 +15,7 @@ module DataChecks
15
15
  end
16
16
  # In ActiveRecord <= 4.2 ActiveRecord::Relation is not an Enumerable!
17
17
  when Enumerable, ActiveRecord::Relation
18
- unless result.empty?
18
+ unless result.to_a.empty? # loads records for ActiveRecord::Relation
19
19
  passing = false
20
20
  count = result.size
21
21
  entries = result
@@ -31,8 +31,8 @@ module DataChecks
31
31
  private
32
32
  def print_summary(counts)
33
33
  statuses = DataChecks::CheckRun.statuses
34
- summary = "Error: #{counts[statuses[:error]]}, "\
35
- "Failing: #{counts[statuses[:failing]]}, "\
34
+ summary = "Error: #{counts[statuses[:error]]}, " \
35
+ "Failing: #{counts[statuses[:failing]]}, " \
36
36
  "Passing: #{counts[statuses[:passing]]}"
37
37
  summary += ", Not Ran: #{counts['not_ran']}" if counts["not_ran"] > 0
38
38
  @io.puts(summary)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DataChecks
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/data_checks.rb CHANGED
@@ -1,20 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "data_checks/check_run"
4
- require "data_checks/check_result"
5
- require "data_checks/check"
6
- require "data_checks/ensure_less"
7
- require "data_checks/ensure_more"
8
- require "data_checks/ensure_no"
9
- require "data_checks/notifiers"
10
- require "data_checks/config"
11
- require "data_checks/runner"
12
- require "data_checks/status_printer"
13
- require "data_checks/version"
3
+ require "active_record"
14
4
 
5
+ require "data_checks/version"
15
6
  require "data_checks/railtie" if defined?(Rails)
16
7
 
17
8
  module DataChecks
9
+ extend ActiveSupport::Autoload
10
+
11
+ autoload :Check
12
+ autoload :CheckResult
13
+ autoload :CheckRun
14
+ autoload :Config
15
+ autoload :EnsureEqual
16
+ autoload :EnsureLess
17
+ autoload :EnsureMore
18
+ autoload :EnsureNo
19
+ autoload :Notifiers
20
+ autoload :Runner
21
+ autoload :StatusPrinter
22
+
18
23
  class << self
19
24
  def config
20
25
  @config ||= Config.new
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: data_checks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - fatkodima
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-21 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2023-11-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4.2'
13
27
  description:
14
28
  email:
15
29
  - fatkodima123@gmail.com
@@ -25,6 +39,7 @@ files:
25
39
  - lib/data_checks/check_result.rb
26
40
  - lib/data_checks/check_run.rb
27
41
  - lib/data_checks/config.rb
42
+ - lib/data_checks/ensure_equal.rb
28
43
  - lib/data_checks/ensure_less.rb
29
44
  - lib/data_checks/ensure_more.rb
30
45
  - lib/data_checks/ensure_no.rb
@@ -66,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
81
  - !ruby/object:Gem::Version
67
82
  version: '0'
68
83
  requirements: []
69
- rubygems_version: 3.3.7
84
+ rubygems_version: 3.4.10
70
85
  signing_key:
71
86
  specification_version: 4
72
87
  summary: Regression testing for data