model_validator 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64f760c55b0d9771afce630e56523e689a3bf1ebd65f21acc003009518f1c340
4
- data.tar.gz: 5854b1987c516583bd2e50a8b97ff576594a6bd9cb3fc1157262ce2995cd4cd4
3
+ metadata.gz: ad05f1a13e54602959a5913973a2faed03b80203233285d48b692fd3310a6b81
4
+ data.tar.gz: a5cf56f9d5d792f675c4ccc918b448772ad4af4d02bdd2647b2a697c0c15b6d6
5
5
  SHA512:
6
- metadata.gz: 6550ec508bfa1a5670f6ad3548e3efddc744dd08df7302d7dbbdbe5afd331e59aa44ca4dbe8681172ed6ed0299a500370d98220153d5a7df63fed0025cc86900
7
- data.tar.gz: e66fb4032041a9b6323a70afd95939f8083736b089d3a27e2f09843c266e43d1d414085ae05d5919dadeac8daf6e8416d03378a2a534bf8e3e1b729a810f733c
6
+ metadata.gz: a629d909b30a1582bb07d9bf5b1884911cb1991c6749ba2fb5fbd75b625648536c1f6ce16c6dcf6d39192a19af0326b6d6c7e96b87e507fc86f76cd3d0d02347
7
+ data.tar.gz: e0440d447f4c11cb7f9fa9a027963476181d1114f18ed9a3fa2e00e4822bd7fd22b8e11ad7f1e019cf57e57d5f45bf9e6a8bc9317b9c9a09fecdf7ea486a3548
data/Gemfile CHANGED
@@ -4,12 +4,10 @@ source "https://rubygems.org"
4
4
 
5
5
  gemspec
6
6
 
7
+ gem "coveralls", require: false
7
8
  gem "rake", "~> 13.0"
8
9
  gem "rspec", "~> 3.0"
9
10
  gem "rubocop", "~> 1.7"
10
-
11
- gem "sqlite3", "~> 1.4"
12
-
13
- gem "rubocop-rspec", "~> 2.2"
14
-
15
11
  gem "rubocop-rake", "~> 0.5.1"
12
+ gem "rubocop-rspec", "~> 2.2"
13
+ gem "sqlite3", "~> 1.4"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- model_validator (1.0.0)
4
+ model_validator (1.1.0)
5
5
  rails (~> 6.1)
6
6
 
7
7
  GEM
@@ -69,13 +69,21 @@ 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)
75
82
  globalid (0.4.2)
76
83
  activesupport (>= 4.2.0)
77
84
  i18n (1.8.5)
78
85
  concurrent-ruby (~> 1.0)
86
+ json (2.5.1)
79
87
  loofah (2.8.0)
80
88
  crass (~> 1.0.2)
81
89
  nokogiri (>= 1.5.9)
@@ -157,6 +165,11 @@ GEM
157
165
  rubocop (~> 1.0)
158
166
  rubocop-ast (>= 1.1.0)
159
167
  ruby-progressbar (1.11.0)
168
+ simplecov (0.16.1)
169
+ docile (~> 1.1)
170
+ json (>= 1.8, < 3)
171
+ simplecov-html (~> 0.10.0)
172
+ simplecov-html (0.10.2)
160
173
  sprockets (4.0.2)
161
174
  concurrent-ruby (~> 1.0)
162
175
  rack (> 1, < 3)
@@ -165,7 +178,12 @@ GEM
165
178
  activesupport (>= 4.0)
166
179
  sprockets (>= 3.0.0)
167
180
  sqlite3 (1.4.2)
181
+ sync (0.5.0)
182
+ term-ansicolor (1.7.1)
183
+ tins (~> 1.0)
168
184
  thor (1.0.1)
185
+ tins (1.28.0)
186
+ sync
169
187
  tzinfo (2.0.3)
170
188
  concurrent-ruby (~> 1.0)
171
189
  unicode-display_width (2.0.0)
@@ -179,6 +197,7 @@ PLATFORMS
179
197
  x86_64-linux
180
198
 
181
199
  DEPENDENCIES
200
+ coveralls
182
201
  model_validator!
183
202
  rake (~> 13.0)
184
203
  rspec (~> 3.0)
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  [![Build Status](https://www.travis-ci.com/jibidus/model_validation.svg?branch=main)](https://www.travis-ci.com/jibidus/model_validation)
2
+ [![Coverage Status](https://coveralls.io/repos/github/jibidus/model_validation/badge.svg?branch=main)](https://coveralls.io/github/jibidus/model_validation?branch=main)
2
3
 
3
4
  # model_validator
4
5
 
@@ -27,10 +28,10 @@ So, because of performances reason, this is only acceptable for tiny databases (
27
28
 
28
29
  ## Installation
29
30
 
30
- Add this line to your application's Gemfile:
31
+ Add this line to your application"s Gemfile:
31
32
 
32
33
  ```ruby
33
- gem 'model_validator'
34
+ gem "model_validator"
34
35
  ```
35
36
 
36
37
  And then execute:
@@ -70,7 +71,7 @@ ModelValidator.validate_all skipped_models: [Model1,Model2]
70
71
 
71
72
  After checking out the repo, run `make install` to install dependencies.
72
73
 
73
- Then, run `make test` to run the tests.
74
+ Then, run `make test` to run the tests (test coverage is available in `coverage/index.html`).
74
75
 
75
76
  Then, run `make lint` to run linters ([rubocop](https://github.com/rubocop-hq/rubocop)).
76
77
 
@@ -78,8 +79,12 @@ To install this gem onto your local machine, run `bundle exec rake install`.
78
79
 
79
80
  ### How to release new version?
80
81
 
81
- - Update the version number in `version.rb`
82
- - run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
82
+ Make sure your are in `main` branch. Then, run:
83
+ ```bash
84
+ rake release:make[major|minor|patch|x.y.z]
85
+ ```
86
+
87
+ Example for building a new minor release: `rake release:make[minor]`
83
88
 
84
89
  ## Why not contributing to existing gem?
85
90
 
@@ -88,7 +93,7 @@ Many already existing gems may do the same, but none are satisfying:
88
93
  - [validb](https://github.com/jgeiger/validb): depends on [sidekiq](https://github.com/mperham/sidekiq)
89
94
  - [validates_blacklist](https://www.rubydoc.info/gems/validates_blacklist/0.0.1): requires to add configuration in each model 😨
90
95
  - [valid_items](https://rubygems.org/gems/valid_items): requires rails eager load 🤔
91
- - [schema-validations](https://github.com/robworley/schema-validations): I don't understand what it really does 🤪
96
+ - [schema-validations](https://github.com/robworley/schema-validations): I don"t understand what it really does 🤪
92
97
 
93
98
  ## Contributing
94
99
 
@@ -100,4 +105,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
100
105
 
101
106
  ## Code of Conduct
102
107
 
103
- 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).
108
+ 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).
@@ -6,55 +6,81 @@ require "rails"
6
6
  module ModelValidator
7
7
  require "model_validator/railtie" if defined?(Rails)
8
8
 
9
+ # Validations summary, with:
10
+ # - violations: number of violations (i.e. number of model which validation failed)
11
+ # - total: total number of validated models
12
+ class Result
13
+ attr_accessor :violations, :total
14
+
15
+ def initialize(violations: 0, total: 0)
16
+ @violations = violations
17
+ @total = total
18
+ end
19
+ end
20
+
9
21
  def self.validate_all(skipped_models: [])
10
22
  if skipped_models.empty?
11
23
  Rails.logger.info "No model skipped"
12
24
  else
13
25
  Rails.logger.info "Skipped model(s): #{skipped_models.map(&:to_s).join(", ")}"
14
26
  end
15
- handler = LogHandler.new
16
- Validator.new(handler, skip_models: skipped_models).run
17
- handler.violations_count
27
+ stats_handler = StatsHandler.new
28
+ handlers = [LogHandler.new, stats_handler]
29
+ Validator.new(handlers: handlers, skip_models: skipped_models).run
30
+ stats_handler.result
18
31
  end
19
32
 
20
33
  # Validation engine, which fetch, and validate each database records
21
34
  class Validator
22
- def initialize(handler, skip_models: [])
23
- @handler = handler
35
+ def initialize(handlers: [], skip_models: [])
36
+ @handlers = handlers
24
37
  @skip_models = skip_models
25
38
  end
26
39
 
27
- def models_to_validate
40
+ def classes_to_validate
28
41
  ActiveRecord::Base.subclasses
29
42
  .reject { |type| type.to_s.include? "::" } # subclassed classes are not our own models
30
43
  .reject { |type| @skip_models.include? type }
31
44
  end
32
45
 
33
46
  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?
47
+ classes_to_validate.each do |model_class|
48
+ @handlers.each { |h| h.try(:on_new_class, model_class) }
49
+ model_class.unscoped.find_each do |model|
50
+ @handlers.each { |h| h.try(:on_violation, model) } unless model.valid?
51
+ @handlers.each { |h| h.try(:after_validation, model) }
38
52
  end
39
53
  end
40
54
  end
41
55
  end
42
56
 
43
- # Validation handler, which logs each violation
57
+ # This handler logs validation progression
44
58
  class LogHandler
45
- attr_reader :violations_count
59
+ def on_new_class(model_class)
60
+ Rails.logger.info "Checking #{model_class}..."
61
+ end
62
+
63
+ def on_violation(model)
64
+ Rails.logger.error "#<#{model.class} id: #{model.id}, errors: #{model.errors.full_messages}>" unless model.valid?
65
+ end
66
+ end
67
+
68
+ # This handler computes validation statistics
69
+ class StatsHandler
70
+ attr_reader :result
46
71
 
47
72
  def initialize
48
- @violations_count = 0
73
+ @result = Result.new(violations: 0, total: 0)
49
74
  end
50
75
 
51
- def start_model(type)
52
- Rails.logger.info "Checking #{type}..."
76
+ def on_new_class(_) end
77
+
78
+ def on_violation(_)
79
+ @result.violations += 1
53
80
  end
54
81
 
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
82
+ def after_validation(_)
83
+ @result.total += 1
58
84
  end
59
85
  end
60
86
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ModelValidator
4
- VERSION = "1.0.0"
4
+ VERSION = "1.1.0"
5
5
  end
@@ -8,19 +8,18 @@ Gem::Specification.new do |spec|
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 = <<~FOO
13
- Many reason may make database violate Active Record validation rules
14
- (database modification without Active Record, migration…).
15
- This raises unexpected error when these records are manipulated by rails.
16
- FOO
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/model_validation"
23
- spec.metadata["changelog_uri"] = "https://github.com/jibidus/model_validation"
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.
@@ -0,0 +1,37 @@
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
+
22
+ next if args[:dry_run]
23
+
24
+ release.git_commit!
25
+
26
+ puts <<~MSG
27
+ Release built.
28
+
29
+ Run following commands to publish version #{release.new_version}:
30
+ $> git push && git push --tags
31
+ $> bundle exec rake release
32
+
33
+ After that, do not forget to report changelog in Github Releases page:
34
+ https://github.com/jibidus/model_validator/releases
35
+ MSG
36
+ end
37
+ 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,72 @@
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
+ private
58
+
59
+ def sub_file_content(file_path, from, to)
60
+ current_content = File.read(file_path)
61
+ modified_content = current_content.sub(from, to)
62
+ raise "Cannot find regexp '#{from}' in file #{file_path}" if modified_content == current_content
63
+
64
+ File.open(file_path, "w") { |file| file << modified_content }
65
+ end
66
+
67
+ def commits_by_type
68
+ Repository.commits_from(current_version)
69
+ .select { |commit| commit.type?(COMMIT_TYPES.keys) }
70
+ .group_by(&:type)
71
+ end
72
+ 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,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: model_validator
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.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-14 00:00:00.000000000 Z
11
+ date: 2021-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -25,9 +25,8 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '6.1'
27
27
  description: |
28
- Many reason may make database violate Active Record validation rules
29
- (database modification without Active Record, migration…).
30
- This raises unexpected error when these records are manipulated by rails.
28
+ Find models in database which violate Active Record validation rules.
29
+ Invalid models may raise unexpected error when updated.
31
30
  email:
32
31
  - jibidus@gmail.com
33
32
  executables: []
@@ -45,21 +44,24 @@ files:
45
44
  - Makefile
46
45
  - README.md
47
46
  - Rakefile
48
- - bin/console
49
- - bin/setup
50
47
  - lib/model_validator.rb
51
48
  - lib/model_validator/Rakefile
52
49
  - lib/model_validator/railtie.rb
53
50
  - lib/model_validator/tasks/db/validate.rake
54
51
  - lib/model_validator/version.rb
55
52
  - model_validator.gemspec
56
- homepage: https://github.com/jibidus/model_validation
53
+ - rakelib/release.rake
54
+ - rakelib/release/commit.rb
55
+ - rakelib/release/release.rb
56
+ - rakelib/release/repository.rb
57
+ - rakelib/release/version.rb
58
+ homepage: https://github.com/jibidus/model_validator
57
59
  licenses:
58
60
  - MIT
59
61
  metadata:
60
- homepage_uri: https://github.com/jibidus/model_validation
61
- source_code_uri: https://github.com/jibidus/model_validation
62
- changelog_uri: https://github.com/jibidus/model_validation
62
+ homepage_uri: https://github.com/jibidus/model_validator
63
+ source_code_uri: https://github.com/jibidus/model_validator
64
+ changelog_uri: https://github.com/jibidus/model_validator
63
65
  post_install_message:
64
66
  rdoc_options: []
65
67
  require_paths:
@@ -78,5 +80,5 @@ requirements: []
78
80
  rubygems_version: 3.1.4
79
81
  signing_key:
80
82
  specification_version: 4
81
- summary: Validate database against Active Record model validations.
83
+ summary: Validate database against Active Record model validations
82
84
  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__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here