db_validator 0.1.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 +7 -0
- data/config/initializers/db_validator.rb +12 -0
- data/lib/db_validator/configuration.rb +39 -0
- data/lib/db_validator/fixer.rb +35 -0
- data/lib/db_validator/railtie.rb +15 -0
- data/lib/db_validator/reporter.rb +70 -0
- data/lib/db_validator/validator.rb +86 -0
- data/lib/db_validator/version.rb +5 -0
- data/lib/db_validator.rb +21 -0
- data/lib/generators/db_validator/install_generator.rb +16 -0
- data/lib/generators/db_validator/templates/initializer.rb +24 -0
- data/lib/tasks/db_validator_tasks.rake +19 -0
- data/readme.md +111 -0
- metadata +141 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d5b1e93e6a494c74779345e004eb7f6050fa5fd4e15cb27846d48fa8390a78ef
|
4
|
+
data.tar.gz: 9ab575840ad1cb722db62b40162b527e4793305ed4255b38eb1166ba5e4786fe
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 20cc83d66461dff7faed7ec1eee28b4c5459152d723403c15b23718554e5ae208e965acde7b3ee4bb2ba030e19bdd86c1e4e63bd0072e7e2bfbfdd25048647e9
|
7
|
+
data.tar.gz: b8e9a4175498cf0f96eec2ed624a9c1be35c6092206bfd7117ecad929f59760236d361cbf524cce37fb603feaafa4ed981f5cbf0308cb0b79a2b2adb2c39a5d5
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
DbValidator.configure do |config|
|
4
|
+
config.only_models = %w[Documents Users]
|
5
|
+
config.batch_size = 500
|
6
|
+
config.limit = 500
|
7
|
+
config.model_limits = {
|
8
|
+
"documents" => 500,
|
9
|
+
"users" => 1000
|
10
|
+
}
|
11
|
+
config.report_format = :json
|
12
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DbValidator
|
4
|
+
class Configuration
|
5
|
+
attr_accessor :only_models, :ignored_models, :ignored_attributes, :batch_size, :report_format, :auto_fix, :limit
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@only_models = []
|
9
|
+
@ignored_models = []
|
10
|
+
@ignored_attributes = {}
|
11
|
+
@batch_size = 1000
|
12
|
+
@report_format = :text
|
13
|
+
@auto_fix = false
|
14
|
+
@limit = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def only_models=(models)
|
18
|
+
@only_models = models.map(&:downcase)
|
19
|
+
end
|
20
|
+
|
21
|
+
def ignored_models
|
22
|
+
@ignored_models ||= []
|
23
|
+
end
|
24
|
+
|
25
|
+
def ignored_models=(models)
|
26
|
+
@ignored_models = models.map(&:downcase)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class << self
|
31
|
+
def configuration
|
32
|
+
@configuration ||= Configuration.new
|
33
|
+
end
|
34
|
+
|
35
|
+
def configure
|
36
|
+
yield(configuration)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DbValidator
|
4
|
+
class Fixer
|
5
|
+
def initialize
|
6
|
+
@fixed_records = 0
|
7
|
+
@failed_fixes = 0
|
8
|
+
end
|
9
|
+
|
10
|
+
def fix_record(record)
|
11
|
+
return false unless record.invalid?
|
12
|
+
|
13
|
+
success = attempt_fix(record)
|
14
|
+
if success
|
15
|
+
@fixed_records += 1
|
16
|
+
else
|
17
|
+
@failed_fixes += 1
|
18
|
+
end
|
19
|
+
success
|
20
|
+
end
|
21
|
+
|
22
|
+
def statistics
|
23
|
+
{
|
24
|
+
fixed_records: @fixed_records,
|
25
|
+
failed_fixes: @failed_fixes
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def attempt_fix(record)
|
32
|
+
record.save
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DbValidator
|
4
|
+
class Railtie < Rails::Railtie
|
5
|
+
railtie_name :db_validator
|
6
|
+
|
7
|
+
rake_tasks do
|
8
|
+
load "tasks/db_validator_tasks.rake"
|
9
|
+
end
|
10
|
+
|
11
|
+
generators do
|
12
|
+
require "generators/db_validator/install_generator"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DbValidator
|
4
|
+
class Reporter
|
5
|
+
def initialize
|
6
|
+
@invalid_records = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def add_invalid_record(record)
|
10
|
+
enhanced_errors = record.errors.map do |error|
|
11
|
+
field_value = record.send(error.attribute)
|
12
|
+
message = error.message
|
13
|
+
|
14
|
+
if error.options[:in].present?
|
15
|
+
"#{error.attribute} #{message} (allowed values: #{error.options[:in].join(', ')}, actual value: #{field_value.inspect})"
|
16
|
+
else
|
17
|
+
"#{error.attribute} #{message} (actual value: #{field_value.inspect})"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
@invalid_records << {
|
22
|
+
model: record.class.name,
|
23
|
+
id: record.id,
|
24
|
+
errors: enhanced_errors
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def generate_report
|
29
|
+
case DbValidator.configuration.report_format
|
30
|
+
when :json
|
31
|
+
generate_json_report
|
32
|
+
else
|
33
|
+
generate_text_report
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def generate_text_report
|
40
|
+
report = StringIO.new
|
41
|
+
report.puts "DbValidator Report"
|
42
|
+
report.puts "=================="
|
43
|
+
report.puts
|
44
|
+
|
45
|
+
if @invalid_records.empty?
|
46
|
+
report.puts "No invalid records found."
|
47
|
+
else
|
48
|
+
report.puts "Found invalid records:"
|
49
|
+
report.puts
|
50
|
+
|
51
|
+
@invalid_records.group_by { |r| r[:model] }.each do |model, records|
|
52
|
+
report.puts "#{model}: #{records.count} invalid records"
|
53
|
+
records.each do |record|
|
54
|
+
report.puts " ID: #{record[:id]}"
|
55
|
+
record[:errors].each do |error|
|
56
|
+
report.puts " - #{error}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
report.puts
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
report.string
|
64
|
+
end
|
65
|
+
|
66
|
+
def generate_json_report
|
67
|
+
@invalid_records.to_json
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ruby-progressbar"
|
4
|
+
require "colorize"
|
5
|
+
|
6
|
+
module DbValidator
|
7
|
+
class Validator
|
8
|
+
def initialize(options = {})
|
9
|
+
@options = options
|
10
|
+
@reporter = Reporter.new
|
11
|
+
@fixer = Fixer.new if DbValidator.configuration.auto_fix
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate_all
|
15
|
+
Rails.application.eager_load! if defined?(Rails)
|
16
|
+
|
17
|
+
models = find_all_models
|
18
|
+
|
19
|
+
models_to_validate = models.select { |model| should_validate_model?(model) }
|
20
|
+
total_models = models_to_validate.size
|
21
|
+
|
22
|
+
models_to_validate.each_with_index do |model, index|
|
23
|
+
Rails.logger.debug "Validating model #{index + 1}/#{total_models}: #{model.name}".colorize(:cyan)
|
24
|
+
validate_model(model)
|
25
|
+
end
|
26
|
+
|
27
|
+
@reporter.generate_report
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def find_all_models
|
33
|
+
# Include all classes inheriting from ActiveRecord::Base
|
34
|
+
ObjectSpace.each_object(Class).select do |klass|
|
35
|
+
klass < ActiveRecord::Base
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def should_validate_model?(model)
|
40
|
+
return false if model.abstract_class?
|
41
|
+
return false unless model.table_exists?
|
42
|
+
|
43
|
+
config = DbValidator.configuration
|
44
|
+
model_name = model.name.downcase
|
45
|
+
return config.only_models.include?(model_name) if config.only_models.any?
|
46
|
+
|
47
|
+
config.ignored_models.exclude?(model_name)
|
48
|
+
end
|
49
|
+
|
50
|
+
def validate_model(model)
|
51
|
+
limit = DbValidator.configuration.limit
|
52
|
+
total_records = limit || model.count
|
53
|
+
|
54
|
+
if total_records.zero?
|
55
|
+
Rails.logger.debug { "No records to validate for model #{model.name}." }
|
56
|
+
return
|
57
|
+
end
|
58
|
+
|
59
|
+
processed_records = 0
|
60
|
+
|
61
|
+
query = model.all
|
62
|
+
query = query.limit(limit) if limit
|
63
|
+
|
64
|
+
query.find_in_batches(batch_size: DbValidator.configuration.batch_size) do |batch|
|
65
|
+
batch.each do |record|
|
66
|
+
validate_record(record)
|
67
|
+
processed_records += 1
|
68
|
+
if (processed_records % 100).zero? || processed_records == total_records
|
69
|
+
Rails.logger.debug "Validated #{processed_records}/#{total_records} records for model #{model.name}".colorize(:green)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
rescue StandardError => e
|
73
|
+
Rails.logger.debug "Error validating #{model.name}: #{e.message}".colorize(:red)
|
74
|
+
end
|
75
|
+
rescue ActiveRecord::StatementInvalid => e
|
76
|
+
Rails.logger.debug { "Skipping validation for #{model.name}: #{e.message}" }
|
77
|
+
end
|
78
|
+
|
79
|
+
def validate_record(record)
|
80
|
+
return if record.valid?
|
81
|
+
|
82
|
+
@reporter.add_invalid_record(record)
|
83
|
+
@fixer&.attempt_fix(record)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/db_validator.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails"
|
4
|
+
require "db_validator/version"
|
5
|
+
require "db_validator/configuration"
|
6
|
+
require "db_validator/validator"
|
7
|
+
require "db_validator/reporter"
|
8
|
+
require "db_validator/fixer"
|
9
|
+
|
10
|
+
module DbValidator
|
11
|
+
class Error < StandardError; end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def validate(options = {})
|
15
|
+
validator = Validator.new(options)
|
16
|
+
validator.validate_all
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
require "db_validator/railtie" if defined?(Rails)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators"
|
4
|
+
require "rails/generators/base"
|
5
|
+
|
6
|
+
module DbValidator
|
7
|
+
module Generators
|
8
|
+
class InstallGenerator < Rails::Generators::Base
|
9
|
+
source_root File.expand_path("templates", __dir__)
|
10
|
+
|
11
|
+
def create_initializer
|
12
|
+
template "initializer.rb", "config/initializers/db_validator.rb"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
DbValidator.configure do |config|
|
4
|
+
# Specify specific models to validate
|
5
|
+
config.only_models = %w[User Post]
|
6
|
+
|
7
|
+
# Ignore specific models from validation
|
8
|
+
# config.ignored_models = ["AdminUser"]
|
9
|
+
|
10
|
+
# Ignore specific attributes for specific models
|
11
|
+
# config.ignored_attributes = {
|
12
|
+
# "User" => ["encrypted_password", "reset_password_token"],
|
13
|
+
# "Post" => ["cached_votes"]
|
14
|
+
# }
|
15
|
+
|
16
|
+
# Set the batch size for processing records (default: 1000)
|
17
|
+
# config.batch_size = 1000
|
18
|
+
|
19
|
+
# Set the report format (:text or :json)
|
20
|
+
# config.report_format = :text
|
21
|
+
|
22
|
+
# Enable automatic fixing of simple validation errors
|
23
|
+
# config.auto_fix = false
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :db_validator do
|
4
|
+
desc "Validate all records in the database"
|
5
|
+
task validate: :environment do
|
6
|
+
if ENV["models"]
|
7
|
+
models = ENV["models"].split(",").map(&:strip).map(&:downcase)
|
8
|
+
DbValidator.configuration.only_models = models
|
9
|
+
end
|
10
|
+
|
11
|
+
DbValidator.configuration.limit = ENV["limit"].to_i if ENV["limit"]
|
12
|
+
|
13
|
+
DbValidator.configuration.report_format = ENV["format"].to_sym if ENV["format"]
|
14
|
+
|
15
|
+
validator = DbValidator::Validator.new
|
16
|
+
report = validator.validate_all
|
17
|
+
puts report
|
18
|
+
end
|
19
|
+
end
|
data/readme.md
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
# DbValidator
|
2
|
+
|
3
|
+
DbValidator helps identify invalid records in your Rails application that don't meet model validation requirements.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'db_validator'
|
11
|
+
```
|
12
|
+
|
13
|
+
Then execute:
|
14
|
+
|
15
|
+
```bash
|
16
|
+
$ bundle install
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself:
|
20
|
+
|
21
|
+
```bash
|
22
|
+
$ gem install db_validator
|
23
|
+
```
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
### Rake Task
|
28
|
+
|
29
|
+
The simplest way to run validation is using the provided rake task:
|
30
|
+
|
31
|
+
#### Validate all models
|
32
|
+
|
33
|
+
```bash
|
34
|
+
$ rake db_validator:validate
|
35
|
+
```
|
36
|
+
|
37
|
+
#### Validate specific models
|
38
|
+
|
39
|
+
```bash
|
40
|
+
$ rake db_validator:validate models=user,post
|
41
|
+
```
|
42
|
+
|
43
|
+
#### Limit the number of records to validate
|
44
|
+
|
45
|
+
```bash
|
46
|
+
$ rake db_validator:validate limit=1000
|
47
|
+
```
|
48
|
+
|
49
|
+
#### Generate JSON report
|
50
|
+
|
51
|
+
```bash
|
52
|
+
$ rake db_validator:validate format=json
|
53
|
+
```
|
54
|
+
|
55
|
+
### Ruby Code
|
56
|
+
|
57
|
+
You can also run validation from your Ruby code:
|
58
|
+
|
59
|
+
#### Validate all models
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
report = DbValidator.validate
|
63
|
+
```
|
64
|
+
|
65
|
+
#### Validate with options
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
report = DbValidator.validate(
|
69
|
+
only_models: ['User', 'Post'],
|
70
|
+
limit: 1000,
|
71
|
+
report_format: :json
|
72
|
+
)
|
73
|
+
```
|
74
|
+
|
75
|
+
## Report Format
|
76
|
+
|
77
|
+
### Text Format (Default)
|
78
|
+
|
79
|
+
```
|
80
|
+
DbValidator Report
|
81
|
+
==================
|
82
|
+
Found invalid records:
|
83
|
+
|
84
|
+
User: 2 invalid records
|
85
|
+
ID: 1
|
86
|
+
email is invalid (actual value: "invalid-email")
|
87
|
+
ID: 2
|
88
|
+
name can't be blank (actual value: "")
|
89
|
+
|
90
|
+
Post: 1 invalid record
|
91
|
+
ID: 5
|
92
|
+
title can't be blank (actual value: "")
|
93
|
+
category is not included in the list (allowed values: news, blog, actual value: "invalid")
|
94
|
+
```
|
95
|
+
|
96
|
+
### JSON Format
|
97
|
+
|
98
|
+
```json
|
99
|
+
[
|
100
|
+
{
|
101
|
+
"model": "User",
|
102
|
+
"id": 1,
|
103
|
+
"errors": ["email is invalid (actual value: \"invalid-email\")"]
|
104
|
+
},
|
105
|
+
{
|
106
|
+
"model": "User",
|
107
|
+
"id": 2,
|
108
|
+
"errors": ["name can't be blank (actual value: \"\")"]
|
109
|
+
}
|
110
|
+
]
|
111
|
+
```
|
metadata
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: db_validator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Krzysztof Duda
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-11-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: database_cleaner-active_record
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.1'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec-rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '6.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '6.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sqlite3
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.4'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.4'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: colorize
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.8.1
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.8.1
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: ruby-progressbar
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.11'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.11'
|
97
|
+
description: A comprehensive solution for validating existing database records in
|
98
|
+
Rails applications
|
99
|
+
email:
|
100
|
+
- duda_krzysztof@outlook.com
|
101
|
+
executables: []
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- config/initializers/db_validator.rb
|
106
|
+
- lib/db_validator.rb
|
107
|
+
- lib/db_validator/configuration.rb
|
108
|
+
- lib/db_validator/fixer.rb
|
109
|
+
- lib/db_validator/railtie.rb
|
110
|
+
- lib/db_validator/reporter.rb
|
111
|
+
- lib/db_validator/validator.rb
|
112
|
+
- lib/db_validator/version.rb
|
113
|
+
- lib/generators/db_validator/install_generator.rb
|
114
|
+
- lib/generators/db_validator/templates/initializer.rb
|
115
|
+
- lib/tasks/db_validator_tasks.rake
|
116
|
+
- readme.md
|
117
|
+
homepage: https://github.com/yourusername/db_validator
|
118
|
+
licenses:
|
119
|
+
- MIT
|
120
|
+
metadata:
|
121
|
+
rubygems_mfa_required: 'true'
|
122
|
+
post_install_message:
|
123
|
+
rdoc_options: []
|
124
|
+
require_paths:
|
125
|
+
- lib
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: 2.7.0
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - ">="
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '0'
|
136
|
+
requirements: []
|
137
|
+
rubygems_version: 3.5.16
|
138
|
+
signing_key:
|
139
|
+
specification_version: 4
|
140
|
+
summary: Database-wide validation for Rails applications
|
141
|
+
test_files: []
|