activevalidation 0.1.0 → 1.0.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.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +32 -9
  3. data/.overcommit.yml +93 -0
  4. data/.rspec +1 -1
  5. data/.rubocop.yml +80 -0
  6. data/.rubocop_todo.yml +7 -0
  7. data/.travis.yml +42 -2
  8. data/.yardops +9 -0
  9. data/Appraisals +27 -0
  10. data/Gemfile +24 -1
  11. data/MIT-LICENSE +20 -0
  12. data/README.md +142 -20
  13. data/Rakefile +21 -3
  14. data/activevalidation.gemspec +35 -25
  15. data/bin/console +4 -7
  16. data/gemfiles/am_5.0.gemfile +17 -0
  17. data/gemfiles/am_5.0.gemfile.lock +159 -0
  18. data/gemfiles/am_5.1.gemfile +17 -0
  19. data/gemfiles/am_5.1.gemfile.lock +159 -0
  20. data/gemfiles/am_5.2.gemfile +17 -0
  21. data/gemfiles/am_5.2.gemfile.lock +159 -0
  22. data/gemfiles/am_6.0.gemfile +18 -0
  23. data/gemfiles/am_6.0.gemfile.lock +158 -0
  24. data/lib/active_validation.rb +27 -0
  25. data/lib/active_validation/base_adapter.rb +103 -0
  26. data/lib/active_validation/configuration.rb +52 -0
  27. data/lib/active_validation/decorator.rb +27 -0
  28. data/lib/active_validation/decorators/consistent_registry.rb +36 -0
  29. data/lib/active_validation/decorators/disallows_duplicates_registry.rb +17 -0
  30. data/lib/active_validation/errors.rb +28 -0
  31. data/lib/active_validation/ext/add_active_validation_context_check.rb +21 -0
  32. data/lib/active_validation/formatters/manifest_name_formatter.rb +13 -0
  33. data/lib/active_validation/formatters/validation_context_formatter.rb +28 -0
  34. data/lib/active_validation/frameworks/rspec.rb +10 -0
  35. data/lib/active_validation/frameworks/rspec/helpers.rb +15 -0
  36. data/lib/active_validation/internal/models/check.rb +51 -0
  37. data/lib/active_validation/internal/models/concerns/to_internal.rb +27 -0
  38. data/lib/active_validation/internal/models/manifest.rb +122 -0
  39. data/lib/active_validation/internal/models/manifest/installer.rb +86 -0
  40. data/lib/active_validation/internal/observers/manifest.rb +114 -0
  41. data/lib/active_validation/model_extension_base.rb +33 -0
  42. data/lib/active_validation/orm_plugins/active_record_plugin/adapter.rb +59 -0
  43. data/lib/active_validation/orm_plugins/active_record_plugin/internals/active_validation/internal_model_extensions/check.rb +11 -0
  44. data/lib/active_validation/orm_plugins/active_record_plugin/model_extension/active_validation/active_record_model_extension.rb +25 -0
  45. data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/check.rb +31 -0
  46. data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/concerns/method_must_be_allowed.rb +38 -0
  47. data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validate_method.rb +9 -0
  48. data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validates_method.rb +9 -0
  49. data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validates_with_method.rb +19 -0
  50. data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/concerns/protect_from_mutable_instance_methods.rb +31 -0
  51. data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/manifest.rb +21 -0
  52. data/lib/active_validation/orm_plugins/active_record_plugin/types/active_validation/type/version.rb +17 -0
  53. data/lib/active_validation/registry.rb +55 -0
  54. data/lib/active_validation/values/base.rb +39 -0
  55. data/lib/active_validation/values/method_name.rb +22 -0
  56. data/lib/active_validation/values/version.rb +17 -0
  57. data/lib/active_validation/verifier.rb +150 -0
  58. data/lib/active_validation/version.rb +5 -0
  59. data/spec/active_validation/base_adapter_spec.rb +23 -0
  60. data/spec/active_validation/configuration_spec.rb +52 -0
  61. data/spec/active_validation/decorators/consistent_registry_spec.rb +117 -0
  62. data/spec/active_validation/decorators/disallows_duplicates_registry_spec.rb +21 -0
  63. data/spec/active_validation/formatters/manifest_name_formatter_spec.rb +7 -0
  64. data/spec/active_validation/formatters/validation_context_formatter_spec.rb +39 -0
  65. data/spec/active_validation/internal/models/check_spec.rb +67 -0
  66. data/spec/active_validation/internal/models/manifest/installer_spec.rb +177 -0
  67. data/spec/active_validation/internal/models/manifest_spec.rb +136 -0
  68. data/spec/active_validation/internal/observers/manifest_spec.rb +201 -0
  69. data/spec/active_validation/model_extension_base_spec.rb +71 -0
  70. data/spec/active_validation/orm_plugins/active_record_plugin/adapter_spec.rb +31 -0
  71. data/spec/active_validation/orm_plugins/active_record_plugin/adapter_spec_orm_specific_spec.rb +84 -0
  72. data/spec/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validate_method_spec.rb +26 -0
  73. data/spec/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validates_method_spec.rb +26 -0
  74. data/spec/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validates_with_method_spec.rb +34 -0
  75. data/spec/active_validation/orm_plugins/active_record_plugin/models/active_validation/check_spec.rb +48 -0
  76. data/spec/active_validation/orm_plugins/active_record_plugin/models/active_validation/manifest_spec.rb +61 -0
  77. data/spec/active_validation/orm_plugins/active_record_plugin/readme_spec.rb +89 -0
  78. data/spec/active_validation/registry_spec.rb +76 -0
  79. data/spec/active_validation/values/base_spec.rb +61 -0
  80. data/spec/active_validation/values/method_name_spec.rb +16 -0
  81. data/spec/active_validation/values/version_spec.rb +36 -0
  82. data/spec/active_validation/verifier_spec.rb +214 -0
  83. data/spec/active_validation_spec.rb +19 -0
  84. data/spec/factories/internal/internal_check.rb +43 -0
  85. data/spec/features/active_record/child_record.feature +32 -0
  86. data/spec/features/active_record/new_record.feature +22 -0
  87. data/spec/features/no_orm/install.feature +19 -0
  88. data/spec/features/no_orm/validate.feature +27 -0
  89. data/spec/features/no_orm/validate_with_multiple_manifests.feature +29 -0
  90. data/spec/features/no_orm/validate_with_multiple_versions.feature +42 -0
  91. data/spec/features/placeholders/be_matcher.rb +7 -0
  92. data/spec/features/placeholders/klass.rb +5 -0
  93. data/spec/features/placeholders/version.rb +11 -0
  94. data/spec/features/placeholders/whether_to.rb +11 -0
  95. data/spec/features/step_definitions/active_record_steps.rb +7 -0
  96. data/spec/features/step_definitions/steps.rb +85 -0
  97. data/spec/orm/active_record/db_adapters/database.mysql.yml +12 -0
  98. data/spec/orm/active_record/db_adapters/database.postgres.yml +11 -0
  99. data/spec/orm/active_record/db_adapters/database.sqlite.yml +8 -0
  100. data/spec/orm/active_record/factories/check/check_validate.rb +8 -0
  101. data/spec/orm/active_record/factories/check/check_validates.rb +8 -0
  102. data/spec/orm/active_record/factories/check/check_validates_with.rb +19 -0
  103. data/spec/orm/active_record/factories/manifest.rb +29 -0
  104. data/spec/orm/active_record/prepare_db.rb +89 -0
  105. data/spec/orm/active_record/setup.rb +11 -0
  106. data/spec/orm/mongoid/setup.rb +15 -0
  107. data/spec/spec_helper.rb +38 -0
  108. data/spec/support/database_cleaner.rb +16 -0
  109. data/spec/support/deferred_garbage_collection.rb +31 -0
  110. data/spec/support/define_constant_macros.rb +17 -0
  111. data/spec/support/factory_bot.rb +12 -0
  112. data/spec/support/helpers.rb +3 -0
  113. data/spec/support/helpers/only_with_active_record.rb +15 -0
  114. data/spec/support/matchers/delegate.rb +50 -0
  115. data/spec/support/matchers/have_attr.rb +58 -0
  116. data/spec/support/mongoid.yml +6 -0
  117. data/spec/support/shared_examples/check_attributes.rb +9 -0
  118. data/spec/support/shared_examples/verifiers_registry.rb +10 -0
  119. data/spec/support/simplecov.rb +11 -0
  120. data/spec/turnip_helper.rb +4 -0
  121. metadata +304 -20
  122. data/lib/activevalidation.rb +0 -6
  123. data/lib/activevalidation/version.rb +0 -3
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe ActiveValidation do
6
+ it ".config method return actual Configuration" do
7
+ expect(subject.config).to be_a ActiveValidation::Configuration
8
+ end
9
+
10
+ it "setups proper default adapter" do
11
+ expect(subject.configuration.orm_adapter.adapter_name).to eq ENV["ORM"]
12
+ end
13
+
14
+ context "verifier_defaults" do
15
+ it "does not raise if no block provided" do
16
+ expect { subject.configuration.verifier_defaults }.not_to raise_error
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Metrics/BlockLength
4
+ FactoryBot.define do
5
+ factory(:internal_check) do
6
+ initialize_with { new(method_name: method_name, argument: argument, options: options) }
7
+ options { {} }
8
+
9
+ factory :internal_check_validate, class: "ActiveValidation::Internal::Models::Check" do
10
+ method_name { "validate" }
11
+ argument { "my_method" }
12
+ end
13
+
14
+ factory :internal_check_validates, class: "ActiveValidation::Internal::Models::Check" do
15
+ method_name { "validates" }
16
+ argument { "name" }
17
+ options { { "presence" => true } }
18
+ end
19
+
20
+ factory :internal_check_validates_with, class: "ActiveValidation::Internal::Models::Check" do
21
+ transient do
22
+ # Generate validator for the argument
23
+ with_validator_klass { true }
24
+ end
25
+
26
+ method_name { "validates_with" }
27
+ argument { "MyValidator" }
28
+
29
+ after(:build) do |record, evaluator|
30
+ next unless evaluator.with_validator_klass
31
+
32
+ klass = Class.new(ActiveModel::Validator) do
33
+ def initialize(*); end
34
+
35
+ def validate(*); end
36
+ end
37
+
38
+ RSpec::Mocks::ConstantMutator.stub(record.argument, klass)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ # rubocop:enable Metrics/BlockLength
@@ -0,0 +1,32 @@
1
+ @active_record
2
+
3
+ Feature: When the class is a child of active_validation class it should
4
+ preform own checks and parent checks with correct versions
5
+
6
+ Background:
7
+ Given class Bar with active validation and superclass ActiveRecord::Base
8
+ And class Foo with active validation and superclass Bar
9
+ And defined versions are:
10
+ | klass | version |
11
+ | Foo | 1 |
12
+ | Foo | 2 |
13
+ | Bar | 1 |
14
+ | Bar | 2 |
15
+
16
+ When klass Bar have method 'parent_method'
17
+ And Bar have manifest version 2 with checks:
18
+ | method_name | argument | options |
19
+ | validates | parent_method | { inclusion: { in: ['v2'] } } |
20
+ And Bar have manifest version 1 with checks:
21
+ | method_name | argument | options |
22
+ | validates | parent_method | { inclusion: { in: ['v1'] } } |
23
+ And store Foo instance in record variable
24
+
25
+
26
+ Scenario: With parent validation check
27
+ When variable record method 'parent_method' returns 'v2'
28
+ Then variable record should be valid
29
+
30
+ Scenario: With out parent validation check
31
+ When variable record method 'parent_method' returns 'v1'
32
+ Then variable record should be valid
@@ -0,0 +1,22 @@
1
+ @active_record
2
+
3
+ Feature: New record do correct checks and store validation version
4
+
5
+ Background:
6
+ Given class Foo with active validation and superclass ActiveRecord::Base
7
+ And defined versions are:
8
+ | klass | version |
9
+ | Foo | 1 |
10
+ When klass Foo have method 'my_method'
11
+ And Foo have manifest version unprovided with checks:
12
+ | method_name | argument | options |
13
+ | validates | my_method | { presence: true } |
14
+
15
+ Scenario: Should use active validation xontext
16
+ Then class Foo instance should not be valid
17
+
18
+ Scenario: Should became valid
19
+ When store Foo instance in record variable
20
+ When variable record method 'my_method' returns something
21
+ Then variable record should be valid
22
+
@@ -0,0 +1,19 @@
1
+ @no_orm
2
+
3
+ Feature: Manual installation is possible
4
+ We are able to install active validation with out any ORM
5
+
6
+ Background:
7
+ Given class Foo with active validation with out ORM
8
+
9
+ Scenario: With defaults and with out any Versions
10
+ When active validation for class Foo installed
11
+ Then class Foo instance should be valid
12
+
13
+ Scenario: With defaults and with defined Versions
14
+ When defined versions are:
15
+ | klass | version |
16
+ | Foo | 23 |
17
+ | Foo | 42 |
18
+ When active validation for class Foo installed
19
+ Then class Foo instance should be valid
@@ -0,0 +1,27 @@
1
+ @no_orm
2
+
3
+ Feature: Validate instance is possible
4
+ With manual installation we can validate the instance with
5
+ provided validations
6
+
7
+ Background:
8
+ Given class Foo with active validation with out ORM
9
+ And defined versions are:
10
+ | klass | version |
11
+ | Foo | 1 |
12
+ When klass Foo have method 'my_method'
13
+ And Foo have manifest version unprovided with checks:
14
+ | method_name | argument | options |
15
+ | validates | my_method | { presence: true } |
16
+ And active validation for class Foo installed
17
+
18
+
19
+ Scenario: The validations from the manifest should apply on the instance with out the context
20
+ Then class Foo instance should not be valid
21
+
22
+ Scenario: The validations from newer manifest should apply on the instance with out the context
23
+ And Foo have manifest version unprovided with checks:
24
+ | method_name | argument | options |
25
+ | validates | my_method | { presence: false } |
26
+
27
+ Then class Foo instance should be valid
@@ -0,0 +1,29 @@
1
+ @no_orm
2
+
3
+ Feature: Validate instance is possible
4
+ With manual installation we can validate the instance with
5
+ provided validations, when there are a few manifests.
6
+
7
+ Background:
8
+ Given class Foo with active validation with out ORM
9
+ And defined versions are:
10
+ | klass | version |
11
+ | Foo | 1 |
12
+ When klass Foo have method 'my_method'
13
+ And Foo have manifest version unprovided with checks:
14
+ | method_name | argument | options |
15
+ | validates | my_method | { presence: false } |
16
+ And active validation for class Foo installed
17
+ And store Foo instance in record variable
18
+ And klass Foo have method 'another_method'
19
+ And Foo have manifest version unprovided with checks:
20
+ | method_name | argument | options |
21
+ | validates | another_method | { presence: true } |
22
+ And active validation for class Foo installed
23
+
24
+ Scenario: The validations from the manifest should not apply on the instance with out the context
25
+ Then variable record should not be valid
26
+
27
+ Scenario: The validations from the manifest should apply on the instance with correct context
28
+ When variable record method 'another_method' returns something
29
+ Then variable record should be valid
@@ -0,0 +1,42 @@
1
+ @no_orm
2
+
3
+ Feature: Validate instance is possible
4
+ With manual installation we can validate the instance with
5
+ provided validations, when there are a few manifests in
6
+ different versions.
7
+
8
+ Background:
9
+ Given class Foo with active validation with out ORM
10
+ And defined versions are:
11
+ | klass | version |
12
+ | Foo | 1 |
13
+ When klass Foo have method 'my_method'
14
+ And Foo have manifest version 1 with checks:
15
+ | method_name | argument | options |
16
+ | validates | my_method | { presence: true } |
17
+ And active validation for class Foo installed
18
+ And store Foo instance in record variable
19
+ And set variable record manifest to current
20
+ And defined versions are:
21
+ | klass | version |
22
+ | Foo | 2 |
23
+ And klass Foo have method 'another_method'
24
+ And Foo have manifest version 2 with checks:
25
+ | method_name | argument | options |
26
+ | validates | another_method | { presence: true } |
27
+ And store Foo instance in record_v2 variable
28
+ And set active validation version for klass Foo to 2
29
+ And active validation for class Foo installed
30
+
31
+
32
+ Scenario: Should ve validated with version 1
33
+ Then variable record should not be valid
34
+ Then variable record error message should be on my_method
35
+
36
+ Scenario: The v2 record should check only another_method and be valid
37
+ When variable record_v2 method 'another_method' returns something
38
+ Then variable record_v2 should be valid
39
+
40
+ Scenario: The v2 record should check only another_method
41
+ Then variable record_v2 should not be valid
42
+ Then variable record_v2 error message should be on another_method
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ placeholder :be_matcher do
4
+ match(/be (\w+)/) do |name|
5
+ "be_#{name}"
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ placeholder :klass do
4
+ match(/[\w|:]+/, &:constantize)
5
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ placeholder :version do
4
+ match(/unprovided|none|undefined/) do
5
+ nil
6
+ end
7
+
8
+ match(/\d+/) do |version|
9
+ version.to_i.tap { |ver| raise("Version must be integer") if ver.zero? }
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ placeholder :whether_to do
4
+ match(/should not/) do
5
+ false
6
+ end
7
+
8
+ match(/should/) do
9
+ true
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ return unless ENV["ORM"] == "active_record"
4
+
5
+ step("class :string with active validation and superclass :klass") do |klass_name, super_klass|
6
+ define_const(klass_name, superclass: super_klass).active_validation
7
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ step("class :string with active validation with out ORM") do |klass_name|
4
+ define_const klass_name do
5
+ include ActiveModel::Validations
6
+ include ActiveValidation::ModelExtensionBase
7
+ active_validation
8
+
9
+ attr_accessor :manifest
10
+ end
11
+ end
12
+
13
+ step("defined versions are:") do |table|
14
+ table.rows.each do |(klass_name, version)|
15
+ define_const "#{klass_name}::Validations::V#{version}"
16
+ end
17
+ end
18
+
19
+ step("active validation for class :klass installed") do |klass|
20
+ klass.active_validation.install
21
+ end
22
+
23
+ step("class :klass instance in context ':string' :whether_to be valid") do |klass, context, expectation|
24
+ expect(klass.new.valid?(context)).to eq expectation
25
+ end
26
+
27
+ step("variable :string in context ':string' :whether_to be valid") do |instance_var_name, context, expectation|
28
+ instance = instance_variable_get "@#{instance_var_name}"
29
+ expect(instance.valid?(context)).to eq expectation
30
+ end
31
+
32
+ step("class :klass instance :whether_to :be_matcher") do |klass, positive, matcher|
33
+ expectation = positive ? :to : :not_to
34
+
35
+ expect(klass.new).send expectation, send(matcher)
36
+ end
37
+
38
+ step("variable :string :whether_to :be_matcher") do |instance_var_name, positive, matcher|
39
+ expectation = positive ? :to : :not_to
40
+ instance = instance_variable_get "@#{instance_var_name}"
41
+
42
+ expect(instance).send expectation, send(matcher)
43
+ end
44
+
45
+ step("klass :klass have method :string") do |klass, method_name|
46
+ klass.send(:define_method, method_name) { nil }
47
+ end
48
+
49
+ # rubocop:disable Security/Eval
50
+ step(":klass have manifest version :version with checks:") do |klass, version, table|
51
+ checks = table.rows.map do |(method_name, argument, options)|
52
+ { method_name: method_name, argument: argument, options: eval(options) }
53
+ end
54
+
55
+ klass.active_validation.add_manifest checks_attributes: checks, version: version
56
+ end
57
+ # rubocop:enable Security/Eval
58
+
59
+ step("store :klass instance in :string variable") do |klass, variable|
60
+ instance_variable_set("@#{variable}", klass.new)
61
+ end
62
+
63
+ step("variable :string method ':string' returns :string") do |instance_var_name, method_name, returns|
64
+ variable = instance_variable_get("@#{instance_var_name}")
65
+ variable.define_singleton_method(method_name) { returns }
66
+ end
67
+
68
+ step("variable :string error message :whether_to be on :string") do |instance_var_name, expectation, method_name|
69
+ variable = instance_variable_get("@#{instance_var_name}")
70
+ check_method = expectation ? :to : :to_not
71
+
72
+ expect(variable.errors.messages).send(check_method, have_key(method_name.to_sym))
73
+ end
74
+
75
+ step("set active validation version for klass :klass to :version") do |klass, version|
76
+ klass.active_validation.version = version.to_i
77
+ end
78
+
79
+ step("set variable :string manifest to :string") do |instance_var_name, state|
80
+ variable = instance_variable_get("@#{instance_var_name}")
81
+ variable.manifest = case state
82
+ when "current" then variable.class.active_validation.current_manifest
83
+ when "none" then nil
84
+ end
85
+ end
@@ -0,0 +1,12 @@
1
+ default: &default
2
+ adapter: mysql2
3
+ encoding: utf8
4
+ database: test
5
+ pool: 5
6
+ username: root
7
+ password:
8
+ host: localhost
9
+
10
+ test:
11
+ <<: *default
12
+ database: test
@@ -0,0 +1,11 @@
1
+ default: &default
2
+ adapter: postgresql
3
+ username: postgres
4
+ password:
5
+ host: localhost
6
+ port: 5432
7
+ database: test
8
+
9
+ test:
10
+ <<: *default
11
+ database: test
@@ -0,0 +1,8 @@
1
+ default: &default
2
+ adapter: sqlite3
3
+ pool: 5
4
+ timeout: 5000
5
+
6
+ test:
7
+ <<: *default
8
+ database: ":memory:"
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ FactoryBot.define do
4
+ factory :check_validate, class: "ActiveValidation::Check::ValidateMethod" do
5
+ argument { "foo_allowed" }
6
+ options { {} }
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ FactoryBot.define do
4
+ factory :check_validates, class: "ActiveValidation::Check::ValidatesMethod" do
5
+ argument { "name" }
6
+ options { { presence: true } }
7
+ end
8
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ FactoryBot.define do
4
+ factory :check_validates_with, class: "ActiveValidation::Check::ValidatesWithMethod" do
5
+ transient do
6
+ # Generate validator for the argument
7
+ with_validator_klass { true }
8
+ end
9
+
10
+ argument { "FooValidator" }
11
+ options { {} }
12
+
13
+ after(:build) do |record, evaluator|
14
+ next unless evaluator.with_validator_klass
15
+
16
+ RSpec::Mocks::ConstantMutator.stub(record.argument, Class.new(ActiveModel::Validator))
17
+ end
18
+ end
19
+ end