model_validator 1.0.0 → 1.3.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/.travis.yml +1 -0
- data/Gemfile +0 -10
- data/Gemfile.lock +26 -4
- data/Makefile +4 -0
- data/README.md +22 -16
- data/lib/model_validator.rb +7 -44
- data/lib/model_validator/log_handler.rb +16 -0
- data/lib/model_validator/stats_handler.rb +25 -0
- data/lib/model_validator/tasks/db/validate.rake +2 -2
- data/lib/model_validator/validator.rb +45 -0
- data/lib/model_validator/version.rb +1 -1
- data/model_validator.gemspec +19 -11
- data/rakelib/release.rake +26 -0
- data/rakelib/release/commit.rb +15 -0
- data/rakelib/release/release.rb +86 -0
- data/rakelib/release/repository.rb +27 -0
- data/rakelib/release/version.rb +27 -0
- metadata +132 -15
- data/bin/console +0 -15
- data/bin/setup +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8aa2a1ac69ee4d57ea5cb34f7c6ebe0a22a7958ab92bef61a4a643705734a780
|
4
|
+
data.tar.gz: e2a2120fc1916a24d98534a98bc6a5d5f6761eabc03c0a70e0e49d45334f33e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 65384c2f8d4c0b76b73505cca1a674f85ed586eb07b685563144c70c263ea4836c546f9fc293f576b6024d5dec6030d372527be884008380ec578393436bfb86
|
7
|
+
data.tar.gz: '029e28fa3733eadfd67453b52ab6966b93753c3dce5e70b1ca2880b94a0b20a2575e3153f0f27d981c16a4119288dca1c4192f0598d409af00de45dd461982f3'
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
model_validator (1.
|
5
|
-
rails (
|
4
|
+
model_validator (1.3.0)
|
5
|
+
rails (>= 5.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
@@ -69,14 +69,24 @@ GEM
|
|
69
69
|
ast (2.4.2)
|
70
70
|
builder (3.2.4)
|
71
71
|
concurrent-ruby (1.1.7)
|
72
|
+
coveralls (0.8.23)
|
73
|
+
json (>= 1.8, < 3)
|
74
|
+
simplecov (~> 0.16.1)
|
75
|
+
term-ansicolor (~> 1.3)
|
76
|
+
thor (>= 0.19.4, < 2.0)
|
77
|
+
tins (~> 1.6)
|
72
78
|
crass (1.0.6)
|
73
79
|
diff-lcs (1.4.4)
|
80
|
+
docile (1.3.5)
|
74
81
|
erubi (1.10.0)
|
82
|
+
factory_bot (6.1.0)
|
83
|
+
activesupport (>= 5.0.0)
|
75
84
|
globalid (0.4.2)
|
76
85
|
activesupport (>= 4.2.0)
|
77
86
|
i18n (1.8.5)
|
78
87
|
concurrent-ruby (~> 1.0)
|
79
|
-
|
88
|
+
json (2.5.1)
|
89
|
+
loofah (2.9.0)
|
80
90
|
crass (~> 1.0.2)
|
81
91
|
nokogiri (>= 1.5.9)
|
82
92
|
mail (2.7.1)
|
@@ -88,7 +98,7 @@ GEM
|
|
88
98
|
mini_mime (1.0.2)
|
89
99
|
mini_portile2 (2.4.0)
|
90
100
|
minitest (5.14.2)
|
91
|
-
nio4r (2.5.
|
101
|
+
nio4r (2.5.5)
|
92
102
|
nokogiri (1.10.10)
|
93
103
|
mini_portile2 (~> 2.4.0)
|
94
104
|
parallel (1.20.1)
|
@@ -157,6 +167,11 @@ GEM
|
|
157
167
|
rubocop (~> 1.0)
|
158
168
|
rubocop-ast (>= 1.1.0)
|
159
169
|
ruby-progressbar (1.11.0)
|
170
|
+
simplecov (0.16.1)
|
171
|
+
docile (~> 1.1)
|
172
|
+
json (>= 1.8, < 3)
|
173
|
+
simplecov-html (~> 0.10.0)
|
174
|
+
simplecov-html (0.10.2)
|
160
175
|
sprockets (4.0.2)
|
161
176
|
concurrent-ruby (~> 1.0)
|
162
177
|
rack (> 1, < 3)
|
@@ -165,7 +180,12 @@ GEM
|
|
165
180
|
activesupport (>= 4.0)
|
166
181
|
sprockets (>= 3.0.0)
|
167
182
|
sqlite3 (1.4.2)
|
183
|
+
sync (0.5.0)
|
184
|
+
term-ansicolor (1.7.1)
|
185
|
+
tins (~> 1.0)
|
168
186
|
thor (1.0.1)
|
187
|
+
tins (1.28.0)
|
188
|
+
sync
|
169
189
|
tzinfo (2.0.3)
|
170
190
|
concurrent-ruby (~> 1.0)
|
171
191
|
unicode-display_width (2.0.0)
|
@@ -179,6 +199,8 @@ PLATFORMS
|
|
179
199
|
x86_64-linux
|
180
200
|
|
181
201
|
DEPENDENCIES
|
202
|
+
coveralls
|
203
|
+
factory_bot
|
182
204
|
model_validator!
|
183
205
|
rake (~> 13.0)
|
184
206
|
rspec (~> 3.0)
|
data/Makefile
CHANGED
@@ -5,6 +5,7 @@ install: ## Install dependencies
|
|
5
5
|
bundle install
|
6
6
|
|
7
7
|
test: ## Test application
|
8
|
+
rm -f db/test.sqlite3
|
8
9
|
bundle exec rspec
|
9
10
|
|
10
11
|
lint: ## Check file format, smell code, conventions…
|
@@ -12,3 +13,6 @@ lint: ## Check file format, smell code, conventions…
|
|
12
13
|
|
13
14
|
lint-fix: ## Fix violations when possible
|
14
15
|
bundle exec rubocop -a
|
16
|
+
|
17
|
+
install-locally: ## Install this gem locally
|
18
|
+
bundle exec rake install
|
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
[](https://www.travis-ci.com/jibidus/model_validator)
|
2
|
+
[](https://coveralls.io/github/jibidus/model_validation?branch=main)
|
3
|
+
[](https://badge.fury.io/rb/model_validator)
|
2
4
|
|
3
5
|
# model_validator
|
4
6
|
|
@@ -14,23 +16,23 @@ This is useful since error may occur when manipulating such data.
|
|
14
16
|
|
15
17
|
It is recommended to use this gem during deployment step:
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
1. restore production database in a staging/preprod/non-production environment
|
20
|
+
2. validate the database
|
21
|
+
3. add missing migrations in case of violations
|
22
|
+
4. repeat validation and fix until there is no more violation
|
23
|
+
5. then, you are ready to deploy your application in production
|
22
24
|
|
23
25
|
## Limitations
|
24
26
|
|
25
27
|
This gem fetch **all** record in database, and, for each record run the Active Record validation.
|
26
|
-
So, because of performances reason, this
|
28
|
+
So, because of performances reason, this may be only acceptable for tiny databases (thousand of records).
|
27
29
|
|
28
30
|
## Installation
|
29
31
|
|
30
|
-
Add this line to your application
|
32
|
+
Add this line to your application"s Gemfile:
|
31
33
|
|
32
34
|
```ruby
|
33
|
-
gem
|
35
|
+
gem "model_validator"
|
34
36
|
```
|
35
37
|
|
36
38
|
And then execute:
|
@@ -70,16 +72,20 @@ ModelValidator.validate_all skipped_models: [Model1,Model2]
|
|
70
72
|
|
71
73
|
After checking out the repo, run `make install` to install dependencies.
|
72
74
|
|
73
|
-
Then, run `make test` to run the tests.
|
75
|
+
Then, run `make test` to run the tests (test coverage is available in `coverage/index.html`).
|
74
76
|
|
75
77
|
Then, run `make lint` to run linters ([rubocop](https://github.com/rubocop-hq/rubocop)).
|
76
78
|
|
77
|
-
To install this gem onto your local machine, run `
|
79
|
+
To install this gem onto your local machine, run `make install-locally`.
|
78
80
|
|
79
81
|
### How to release new version?
|
80
82
|
|
81
|
-
|
82
|
-
|
83
|
+
Make sure your are in `main` branch. Then, run:
|
84
|
+
```bash
|
85
|
+
rake release:make[major|minor|patch|x.y.z]
|
86
|
+
```
|
87
|
+
|
88
|
+
Example for building a new minor release: `rake release:make[minor]`
|
83
89
|
|
84
90
|
## Why not contributing to existing gem?
|
85
91
|
|
@@ -87,8 +93,8 @@ Many already existing gems may do the same, but none are satisfying:
|
|
87
93
|
|
88
94
|
- [validb](https://github.com/jgeiger/validb): depends on [sidekiq](https://github.com/mperham/sidekiq)
|
89
95
|
- [validates_blacklist](https://www.rubydoc.info/gems/validates_blacklist/0.0.1): requires to add configuration in each model 😨
|
90
|
-
- [valid_items](https://rubygems.org/gems/valid_items):
|
91
|
-
- [schema-validations](https://github.com/robworley/schema-validations): I
|
96
|
+
- [valid_items](https://rubygems.org/gems/valid_items): not compliant with rails 6 + cannot find sources to contribute
|
97
|
+
- [schema-validations](https://github.com/robworley/schema-validations): I didn't understand what it really does 🤪
|
92
98
|
|
93
99
|
## Contributing
|
94
100
|
|
@@ -100,4 +106,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
100
106
|
|
101
107
|
## Code of Conduct
|
102
108
|
|
103
|
-
Everyone interacting in the ModelValidator project
|
109
|
+
Everyone interacting in the ModelValidator project"s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/model_validator/blob/master/CODE_OF_CONDUCT.md).
|
data/lib/model_validator.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "rails"
|
4
|
+
require_relative "model_validator/stats_handler"
|
5
|
+
require_relative "model_validator/log_handler"
|
6
|
+
require_relative "model_validator/validator"
|
4
7
|
|
5
8
|
# Validate models in database according Active Record model validation rules
|
6
9
|
module ModelValidator
|
@@ -12,49 +15,9 @@ module ModelValidator
|
|
12
15
|
else
|
13
16
|
Rails.logger.info "Skipped model(s): #{skipped_models.map(&:to_s).join(", ")}"
|
14
17
|
end
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
# Validation engine, which fetch, and validate each database records
|
21
|
-
class Validator
|
22
|
-
def initialize(handler, skip_models: [])
|
23
|
-
@handler = handler
|
24
|
-
@skip_models = skip_models
|
25
|
-
end
|
26
|
-
|
27
|
-
def models_to_validate
|
28
|
-
ActiveRecord::Base.subclasses
|
29
|
-
.reject { |type| type.to_s.include? "::" } # subclassed classes are not our own models
|
30
|
-
.reject { |type| @skip_models.include? type }
|
31
|
-
end
|
32
|
-
|
33
|
-
def run
|
34
|
-
models_to_validate.each do |type|
|
35
|
-
@handler.start_model type
|
36
|
-
type.unscoped.find_each do |record|
|
37
|
-
@handler.on_violation(type, record) unless record.valid?
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# Validation handler, which logs each violation
|
44
|
-
class LogHandler
|
45
|
-
attr_reader :violations_count
|
46
|
-
|
47
|
-
def initialize
|
48
|
-
@violations_count = 0
|
49
|
-
end
|
50
|
-
|
51
|
-
def start_model(type)
|
52
|
-
Rails.logger.info "Checking #{type}..."
|
53
|
-
end
|
54
|
-
|
55
|
-
def on_violation(type, record)
|
56
|
-
Rails.logger.error "#<#{type} id: #{record.id}, errors: #{record.errors.full_messages}>" unless record.valid?
|
57
|
-
@violations_count += 1
|
58
|
-
end
|
18
|
+
stats_handler = StatsHandler.new
|
19
|
+
handlers = [LogHandler.new, stats_handler]
|
20
|
+
Validator.new(handlers: handlers, skip_models: skipped_models).run
|
21
|
+
stats_handler.result
|
59
22
|
end
|
60
23
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails"
|
4
|
+
|
5
|
+
module ModelValidator
|
6
|
+
# This handler logs validation progression
|
7
|
+
class LogHandler
|
8
|
+
def on_new_class(model_class)
|
9
|
+
Rails.logger.info "Checking #{model_class.count} #{model_class}…"
|
10
|
+
end
|
11
|
+
|
12
|
+
def on_violation(model)
|
13
|
+
Rails.logger.error "#<#{model.class} id: #{model.id}, errors: #{model.errors.full_messages}>" unless model.valid?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ModelValidator
|
4
|
+
# Validations summary, with:
|
5
|
+
# - violations: number of violations (i.e. number of model which validation failed)
|
6
|
+
# - total: total number of validated models
|
7
|
+
Result = Struct.new(:violations, :total)
|
8
|
+
|
9
|
+
# This handler computes validation statistics
|
10
|
+
class StatsHandler
|
11
|
+
attr_reader :result
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@result = Result.new(0, 0)
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_violation(_)
|
18
|
+
@result.violations += 1
|
19
|
+
end
|
20
|
+
|
21
|
+
def after_validation(_)
|
22
|
+
@result.total += 1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -7,7 +7,7 @@ namespace :db do
|
|
7
7
|
task validate: :environment do
|
8
8
|
Rails.logger.info "Validate database (this will take some time)…"
|
9
9
|
skipped_models = (ENV["MODEL_VALIDATOR_SKIPPED_MODELS"] || "").split(",")
|
10
|
-
|
11
|
-
Rails.logger.info "Validation finished with #{
|
10
|
+
result = ModelValidator.validate_all(skipped_models: skipped_models)
|
11
|
+
Rails.logger.info "Validation finished with #{result.violations}/#{result.total} violation(s)"
|
12
12
|
end
|
13
13
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails"
|
4
|
+
|
5
|
+
module ModelValidator
|
6
|
+
# ApplicationRecord is the base class used to loop up for all models to validate.
|
7
|
+
# So this class is mandatory for ModelValidator to work well.
|
8
|
+
class ApplicationRecordNotFound < StandardError
|
9
|
+
def message
|
10
|
+
<<~MSG
|
11
|
+
ApplicationRecord not found.
|
12
|
+
model_validator requires that all models extends a super class ApplicationRecord.
|
13
|
+
This is expected in a rails application since rails 5.0.
|
14
|
+
MSG
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Validation engine, which fetch, and validate each database records
|
19
|
+
class Validator
|
20
|
+
def initialize(handlers: [], skip_models: [])
|
21
|
+
@handlers = handlers
|
22
|
+
@skip_models = skip_models
|
23
|
+
end
|
24
|
+
|
25
|
+
def classes_to_validate
|
26
|
+
raise ApplicationRecordNotFound unless defined?(ApplicationRecord)
|
27
|
+
|
28
|
+
Rails.application.try(:eager_load!) if Rails.env.development?
|
29
|
+
ApplicationRecord.descendants
|
30
|
+
.reject(&:abstract_class)
|
31
|
+
.select { |type| type.subclasses.empty? }
|
32
|
+
.reject { |type| @skip_models.include? type }
|
33
|
+
end
|
34
|
+
|
35
|
+
def run
|
36
|
+
classes_to_validate.each do |model_class|
|
37
|
+
@handlers.each { |h| h.try(:on_new_class, model_class) }
|
38
|
+
model_class.unscoped.find_each do |model|
|
39
|
+
@handlers.each { |h| h.try(:on_violation, model) } unless model.valid?
|
40
|
+
@handlers.each { |h| h.try(:after_validation, model) }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/model_validator.gemspec
CHANGED
@@ -2,25 +2,24 @@
|
|
2
2
|
|
3
3
|
require_relative "lib/model_validator/version"
|
4
4
|
|
5
|
-
Gem::Specification.new do |spec|
|
5
|
+
Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
|
6
6
|
spec.name = "model_validator"
|
7
7
|
spec.version = ModelValidator::VERSION
|
8
8
|
spec.authors = ["Jibidus"]
|
9
9
|
spec.email = ["jibidus@gmail.com"]
|
10
10
|
|
11
|
-
spec.summary = "Validate database against Active Record model validations
|
12
|
-
spec.description = <<~
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
spec.homepage = "https://github.com/jibidus/model_validation"
|
11
|
+
spec.summary = "Validate database against Active Record model validations"
|
12
|
+
spec.description = <<~DESC
|
13
|
+
Find models in database which violate Active Record validation rules.
|
14
|
+
Invalid models may raise unexpected error when updated.
|
15
|
+
DESC
|
16
|
+
spec.homepage = "https://github.com/jibidus/model_validator"
|
18
17
|
spec.license = "MIT"
|
19
18
|
spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
|
20
19
|
|
21
20
|
spec.metadata["homepage_uri"] = spec.homepage
|
22
|
-
spec.metadata["source_code_uri"] = "https://github.com/jibidus/
|
23
|
-
spec.metadata["changelog_uri"] = "https://github.com/jibidus/
|
21
|
+
spec.metadata["source_code_uri"] = "https://github.com/jibidus/model_validator"
|
22
|
+
spec.metadata["changelog_uri"] = "https://github.com/jibidus/model_validator"
|
24
23
|
|
25
24
|
# Specify which files should be added to the gem when it is released.
|
26
25
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
@@ -31,7 +30,16 @@ Gem::Specification.new do |spec|
|
|
31
30
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
32
31
|
spec.require_paths = ["lib"]
|
33
32
|
|
34
|
-
spec.
|
33
|
+
spec.add_runtime_dependency "rails", ">= 5.0"
|
34
|
+
|
35
|
+
spec.add_development_dependency "coveralls"
|
36
|
+
spec.add_development_dependency "factory_bot"
|
37
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
38
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
39
|
+
spec.add_development_dependency "rubocop", "~> 1.7"
|
40
|
+
spec.add_development_dependency "rubocop-rake", "~> 0.5.1"
|
41
|
+
spec.add_development_dependency "rubocop-rspec", "~> 2.2"
|
42
|
+
spec.add_development_dependency "sqlite3", "~> 1.4"
|
35
43
|
|
36
44
|
# For more information and examples about making a new gem, checkout our
|
37
45
|
# guide at: https://bundler.io/guides/creating_gem.html
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "./rakelib/release/release"
|
4
|
+
|
5
|
+
namespace :release do
|
6
|
+
desc <<~DESC
|
7
|
+
Build new release.
|
8
|
+
- bump_type (mandatory): [major|minor|patch|x.y.z]
|
9
|
+
- dry_run (optional): skip commit, tag and publishing
|
10
|
+
DESC
|
11
|
+
task :make, [:bump_type, :dry_run] do |_, args|
|
12
|
+
release = Release.new args[:bump_type]
|
13
|
+
puts "Bump version from #{release.current_version} to #{release.new_version}"
|
14
|
+
release.apply!
|
15
|
+
|
16
|
+
puts
|
17
|
+
puts "#{release.new_version} changelog"
|
18
|
+
puts "---------------------------------------------------------------------"
|
19
|
+
puts release.changelog
|
20
|
+
puts "---------------------------------------------------------------------"
|
21
|
+
next if args[:dry_run]
|
22
|
+
|
23
|
+
release.git_commit!
|
24
|
+
puts release.publishing_instructions
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Represents a commit in a git repository
|
4
|
+
class Commit
|
5
|
+
attr_reader :type, :message
|
6
|
+
|
7
|
+
def initialize(type, message)
|
8
|
+
@type = type
|
9
|
+
@message = message
|
10
|
+
end
|
11
|
+
|
12
|
+
def type?(types)
|
13
|
+
types.include? @type
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "./rakelib/release/repository"
|
4
|
+
require "./rakelib/release/version"
|
5
|
+
require "./lib/model_validator/version"
|
6
|
+
|
7
|
+
AUTHORIZED_BRANCH = "main"
|
8
|
+
|
9
|
+
# All commit message prefix to include in changelog
|
10
|
+
COMMIT_TYPES = {
|
11
|
+
"tada" => "Feature",
|
12
|
+
"bug" => "Bug fix"
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
# This class can create and publish a new version of the current gem
|
16
|
+
class Release
|
17
|
+
GEM_NAME = "model_validator"
|
18
|
+
VERSION_FILE = "lib/model_validator/version.rb"
|
19
|
+
GEMFILE_LOCK = "Gemfile.lock"
|
20
|
+
|
21
|
+
def initialize(type)
|
22
|
+
@type = type
|
23
|
+
end
|
24
|
+
|
25
|
+
def current_version
|
26
|
+
Version.new(*ModelValidator::VERSION.split(".").map(&:to_i))
|
27
|
+
end
|
28
|
+
|
29
|
+
def new_version
|
30
|
+
@new_version ||= current_version.bump(@type)
|
31
|
+
end
|
32
|
+
|
33
|
+
def apply!
|
34
|
+
if Repository.current_branch != AUTHORIZED_BRANCH
|
35
|
+
raise <<~MSG
|
36
|
+
You can only release new version from '#{AUTHORIZED_BRANCH}' branch.
|
37
|
+
Current branch: '#{Repository.current_branch}'
|
38
|
+
MSG
|
39
|
+
end
|
40
|
+
|
41
|
+
sub_file_content VERSION_FILE, current_version.to_s, new_version.to_s
|
42
|
+
sub_file_content GEMFILE_LOCK, "#{GEM_NAME} (#{current_version})", "#{GEM_NAME} (#{new_version})"
|
43
|
+
end
|
44
|
+
|
45
|
+
def changelog
|
46
|
+
commits_by_type.map do |type, commits|
|
47
|
+
messages_list = commits.map { |commit| "- #{commit.message}\n" }.join
|
48
|
+
"# #{COMMIT_TYPES[type]}\n#{messages_list}"
|
49
|
+
end.join("\n")
|
50
|
+
end
|
51
|
+
|
52
|
+
def git_commit!
|
53
|
+
`git add #{VERSION_FILE} #{GEMFILE_LOCK}`
|
54
|
+
`git commit -m ":label: release version #{new_version}"`
|
55
|
+
end
|
56
|
+
|
57
|
+
def publishing_instructions
|
58
|
+
<<~MSG
|
59
|
+
New commit created with the release.
|
60
|
+
|
61
|
+
Run following commands to publish version #{new_version}:
|
62
|
+
$> git push
|
63
|
+
$> bundle exec rake release
|
64
|
+
|
65
|
+
Then edit tag with changelog:
|
66
|
+
$> git tag v#{new_version} -f -a
|
67
|
+
$> git push -f --tags
|
68
|
+
MSG
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def sub_file_content(file_path, from, to)
|
74
|
+
current_content = File.read(file_path)
|
75
|
+
modified_content = current_content.sub(from, to)
|
76
|
+
raise "Cannot find regexp '#{from}' in file #{file_path}" if modified_content == current_content
|
77
|
+
|
78
|
+
File.open(file_path, "w") { |file| file << modified_content }
|
79
|
+
end
|
80
|
+
|
81
|
+
def commits_by_type
|
82
|
+
Repository.commits_from(current_version)
|
83
|
+
.select { |commit| commit.type?(COMMIT_TYPES.keys) }
|
84
|
+
.group_by(&:type)
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "./rakelib/release/commit"
|
4
|
+
|
5
|
+
# This module contains many methods to manipulate current git repository
|
6
|
+
module Repository
|
7
|
+
def self.current_branch
|
8
|
+
`git rev-parse --abbrev-ref HEAD`.strip
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.commits_from(tag)
|
12
|
+
logs_from("v#{tag}").sort
|
13
|
+
.uniq
|
14
|
+
.map do |commit_message|
|
15
|
+
_, type, message = commit_message.split(":", 3).map(&:strip)
|
16
|
+
if message.nil?
|
17
|
+
message = type
|
18
|
+
type = "unknown"
|
19
|
+
end
|
20
|
+
Commit.new(type, message)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.logs_from(revision)
|
25
|
+
`git log #{revision}..HEAD --pretty=format:"%s"`.split("\n")
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Represent a gem version, which can be bumped for new release.
|
4
|
+
class Version
|
5
|
+
def initialize(major, minor, patch)
|
6
|
+
@major = major
|
7
|
+
@minor = minor
|
8
|
+
@patch = patch
|
9
|
+
end
|
10
|
+
|
11
|
+
def bump(release_type)
|
12
|
+
case release_type
|
13
|
+
when "major"
|
14
|
+
Version.new(@major + 1, 0, 0)
|
15
|
+
when "minor"
|
16
|
+
Version.new(@major, @minor + 1, 0)
|
17
|
+
when "patch"
|
18
|
+
Version.new(@major, @minor, @patch + 1)
|
19
|
+
else
|
20
|
+
raise "Unknonwn bump type '#{release_type}'"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
[@major, @minor, @patch].join(".")
|
26
|
+
end
|
27
|
+
end
|
metadata
CHANGED
@@ -1,33 +1,144 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: model_validator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jibidus
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-02-
|
11
|
+
date: 2021-02-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '5.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: coveralls
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: factory_bot
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '13.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '13.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.7'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.7'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop-rake
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.5.1
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.5.1
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop-rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '2.2'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '2.2'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: sqlite3
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '1.4'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
22
134
|
version_requirements: !ruby/object:Gem::Requirement
|
23
135
|
requirements:
|
24
136
|
- - "~>"
|
25
137
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
138
|
+
version: '1.4'
|
27
139
|
description: |
|
28
|
-
|
29
|
-
|
30
|
-
This raises unexpected error when these records are manipulated by rails.
|
140
|
+
Find models in database which violate Active Record validation rules.
|
141
|
+
Invalid models may raise unexpected error when updated.
|
31
142
|
email:
|
32
143
|
- jibidus@gmail.com
|
33
144
|
executables: []
|
@@ -45,21 +156,27 @@ files:
|
|
45
156
|
- Makefile
|
46
157
|
- README.md
|
47
158
|
- Rakefile
|
48
|
-
- bin/console
|
49
|
-
- bin/setup
|
50
159
|
- lib/model_validator.rb
|
51
160
|
- lib/model_validator/Rakefile
|
161
|
+
- lib/model_validator/log_handler.rb
|
52
162
|
- lib/model_validator/railtie.rb
|
163
|
+
- lib/model_validator/stats_handler.rb
|
53
164
|
- lib/model_validator/tasks/db/validate.rake
|
165
|
+
- lib/model_validator/validator.rb
|
54
166
|
- lib/model_validator/version.rb
|
55
167
|
- model_validator.gemspec
|
56
|
-
|
168
|
+
- rakelib/release.rake
|
169
|
+
- rakelib/release/commit.rb
|
170
|
+
- rakelib/release/release.rb
|
171
|
+
- rakelib/release/repository.rb
|
172
|
+
- rakelib/release/version.rb
|
173
|
+
homepage: https://github.com/jibidus/model_validator
|
57
174
|
licenses:
|
58
175
|
- MIT
|
59
176
|
metadata:
|
60
|
-
homepage_uri: https://github.com/jibidus/
|
61
|
-
source_code_uri: https://github.com/jibidus/
|
62
|
-
changelog_uri: https://github.com/jibidus/
|
177
|
+
homepage_uri: https://github.com/jibidus/model_validator
|
178
|
+
source_code_uri: https://github.com/jibidus/model_validator
|
179
|
+
changelog_uri: https://github.com/jibidus/model_validator
|
63
180
|
post_install_message:
|
64
181
|
rdoc_options: []
|
65
182
|
require_paths:
|
@@ -78,5 +195,5 @@ requirements: []
|
|
78
195
|
rubygems_version: 3.1.4
|
79
196
|
signing_key:
|
80
197
|
specification_version: 4
|
81
|
-
summary: Validate database against Active Record model validations
|
198
|
+
summary: Validate database against Active Record model validations
|
82
199
|
test_files: []
|
data/bin/console
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require "bundler/setup"
|
5
|
-
require "model_validator"
|
6
|
-
|
7
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
-
# with your gem easier. You can also use a different console, if you like.
|
9
|
-
|
10
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
-
# require "pry"
|
12
|
-
# Pry.start
|
13
|
-
|
14
|
-
require "irb"
|
15
|
-
IRB.start(__FILE__)
|