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.
- checksums.yaml +4 -4
- data/.gitignore +32 -9
- data/.overcommit.yml +93 -0
- data/.rspec +1 -1
- data/.rubocop.yml +80 -0
- data/.rubocop_todo.yml +7 -0
- data/.travis.yml +42 -2
- data/.yardops +9 -0
- data/Appraisals +27 -0
- data/Gemfile +24 -1
- data/MIT-LICENSE +20 -0
- data/README.md +142 -20
- data/Rakefile +21 -3
- data/activevalidation.gemspec +35 -25
- data/bin/console +4 -7
- data/gemfiles/am_5.0.gemfile +17 -0
- data/gemfiles/am_5.0.gemfile.lock +159 -0
- data/gemfiles/am_5.1.gemfile +17 -0
- data/gemfiles/am_5.1.gemfile.lock +159 -0
- data/gemfiles/am_5.2.gemfile +17 -0
- data/gemfiles/am_5.2.gemfile.lock +159 -0
- data/gemfiles/am_6.0.gemfile +18 -0
- data/gemfiles/am_6.0.gemfile.lock +158 -0
- data/lib/active_validation.rb +27 -0
- data/lib/active_validation/base_adapter.rb +103 -0
- data/lib/active_validation/configuration.rb +52 -0
- data/lib/active_validation/decorator.rb +27 -0
- data/lib/active_validation/decorators/consistent_registry.rb +36 -0
- data/lib/active_validation/decorators/disallows_duplicates_registry.rb +17 -0
- data/lib/active_validation/errors.rb +28 -0
- data/lib/active_validation/ext/add_active_validation_context_check.rb +21 -0
- data/lib/active_validation/formatters/manifest_name_formatter.rb +13 -0
- data/lib/active_validation/formatters/validation_context_formatter.rb +28 -0
- data/lib/active_validation/frameworks/rspec.rb +10 -0
- data/lib/active_validation/frameworks/rspec/helpers.rb +15 -0
- data/lib/active_validation/internal/models/check.rb +51 -0
- data/lib/active_validation/internal/models/concerns/to_internal.rb +27 -0
- data/lib/active_validation/internal/models/manifest.rb +122 -0
- data/lib/active_validation/internal/models/manifest/installer.rb +86 -0
- data/lib/active_validation/internal/observers/manifest.rb +114 -0
- data/lib/active_validation/model_extension_base.rb +33 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/adapter.rb +59 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/internals/active_validation/internal_model_extensions/check.rb +11 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/model_extension/active_validation/active_record_model_extension.rb +25 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/check.rb +31 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/concerns/method_must_be_allowed.rb +38 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validate_method.rb +9 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validates_method.rb +9 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validates_with_method.rb +19 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/concerns/protect_from_mutable_instance_methods.rb +31 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/models/active_validation/manifest.rb +21 -0
- data/lib/active_validation/orm_plugins/active_record_plugin/types/active_validation/type/version.rb +17 -0
- data/lib/active_validation/registry.rb +55 -0
- data/lib/active_validation/values/base.rb +39 -0
- data/lib/active_validation/values/method_name.rb +22 -0
- data/lib/active_validation/values/version.rb +17 -0
- data/lib/active_validation/verifier.rb +150 -0
- data/lib/active_validation/version.rb +5 -0
- data/spec/active_validation/base_adapter_spec.rb +23 -0
- data/spec/active_validation/configuration_spec.rb +52 -0
- data/spec/active_validation/decorators/consistent_registry_spec.rb +117 -0
- data/spec/active_validation/decorators/disallows_duplicates_registry_spec.rb +21 -0
- data/spec/active_validation/formatters/manifest_name_formatter_spec.rb +7 -0
- data/spec/active_validation/formatters/validation_context_formatter_spec.rb +39 -0
- data/spec/active_validation/internal/models/check_spec.rb +67 -0
- data/spec/active_validation/internal/models/manifest/installer_spec.rb +177 -0
- data/spec/active_validation/internal/models/manifest_spec.rb +136 -0
- data/spec/active_validation/internal/observers/manifest_spec.rb +201 -0
- data/spec/active_validation/model_extension_base_spec.rb +71 -0
- data/spec/active_validation/orm_plugins/active_record_plugin/adapter_spec.rb +31 -0
- data/spec/active_validation/orm_plugins/active_record_plugin/adapter_spec_orm_specific_spec.rb +84 -0
- data/spec/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validate_method_spec.rb +26 -0
- data/spec/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validates_method_spec.rb +26 -0
- data/spec/active_validation/orm_plugins/active_record_plugin/models/active_validation/check/validates_with_method_spec.rb +34 -0
- data/spec/active_validation/orm_plugins/active_record_plugin/models/active_validation/check_spec.rb +48 -0
- data/spec/active_validation/orm_plugins/active_record_plugin/models/active_validation/manifest_spec.rb +61 -0
- data/spec/active_validation/orm_plugins/active_record_plugin/readme_spec.rb +89 -0
- data/spec/active_validation/registry_spec.rb +76 -0
- data/spec/active_validation/values/base_spec.rb +61 -0
- data/spec/active_validation/values/method_name_spec.rb +16 -0
- data/spec/active_validation/values/version_spec.rb +36 -0
- data/spec/active_validation/verifier_spec.rb +214 -0
- data/spec/active_validation_spec.rb +19 -0
- data/spec/factories/internal/internal_check.rb +43 -0
- data/spec/features/active_record/child_record.feature +32 -0
- data/spec/features/active_record/new_record.feature +22 -0
- data/spec/features/no_orm/install.feature +19 -0
- data/spec/features/no_orm/validate.feature +27 -0
- data/spec/features/no_orm/validate_with_multiple_manifests.feature +29 -0
- data/spec/features/no_orm/validate_with_multiple_versions.feature +42 -0
- data/spec/features/placeholders/be_matcher.rb +7 -0
- data/spec/features/placeholders/klass.rb +5 -0
- data/spec/features/placeholders/version.rb +11 -0
- data/spec/features/placeholders/whether_to.rb +11 -0
- data/spec/features/step_definitions/active_record_steps.rb +7 -0
- data/spec/features/step_definitions/steps.rb +85 -0
- data/spec/orm/active_record/db_adapters/database.mysql.yml +12 -0
- data/spec/orm/active_record/db_adapters/database.postgres.yml +11 -0
- data/spec/orm/active_record/db_adapters/database.sqlite.yml +8 -0
- data/spec/orm/active_record/factories/check/check_validate.rb +8 -0
- data/spec/orm/active_record/factories/check/check_validates.rb +8 -0
- data/spec/orm/active_record/factories/check/check_validates_with.rb +19 -0
- data/spec/orm/active_record/factories/manifest.rb +29 -0
- data/spec/orm/active_record/prepare_db.rb +89 -0
- data/spec/orm/active_record/setup.rb +11 -0
- data/spec/orm/mongoid/setup.rb +15 -0
- data/spec/spec_helper.rb +38 -0
- data/spec/support/database_cleaner.rb +16 -0
- data/spec/support/deferred_garbage_collection.rb +31 -0
- data/spec/support/define_constant_macros.rb +17 -0
- data/spec/support/factory_bot.rb +12 -0
- data/spec/support/helpers.rb +3 -0
- data/spec/support/helpers/only_with_active_record.rb +15 -0
- data/spec/support/matchers/delegate.rb +50 -0
- data/spec/support/matchers/have_attr.rb +58 -0
- data/spec/support/mongoid.yml +6 -0
- data/spec/support/shared_examples/check_attributes.rb +9 -0
- data/spec/support/shared_examples/verifiers_registry.rb +10 -0
- data/spec/support/simplecov.rb +11 -0
- data/spec/turnip_helper.rb +4 -0
- metadata +304 -20
- data/lib/activevalidation.rb +0 -6
- data/lib/activevalidation/version.rb +0 -3
data/spec/active_validation/orm_plugins/active_record_plugin/models/active_validation/check_spec.rb
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe ActiveValidation::Check, type: :active_record do
|
|
4
|
+
it "return empty collection" do
|
|
5
|
+
expect(described_class.all).to be_empty
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
%i[update update_attribute update_attributes].each do |method|
|
|
9
|
+
it "raises on #{method}" do
|
|
10
|
+
expect { subject.send(method) }.to raise_error ActiveValidation::Errors::ImmutableError
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context "#method_name" do
|
|
15
|
+
it { expect { subject.method_name }.to raise_error NotImplementedError }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context "#method_name=" do
|
|
19
|
+
it("Set correct type") do
|
|
20
|
+
subject.method_name = "foo"
|
|
21
|
+
expect(subject.type).to eq "FooMethod"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context "#to_internal_check" do
|
|
26
|
+
%i[check_validate check_validates check_validates_with].each do |type|
|
|
27
|
+
context(type) do
|
|
28
|
+
let(:subject) { build type }
|
|
29
|
+
|
|
30
|
+
it "produces right class" do
|
|
31
|
+
expect(subject.to_internal_check).to be_a ActiveValidation::Internal::Models::Check
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context "has value" do
|
|
35
|
+
%w[method_name argument].each do |key|
|
|
36
|
+
it key.to_s do
|
|
37
|
+
expect(subject.to_internal_check.public_send(key)).to eq subject.public_send(key)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "options" do
|
|
41
|
+
expect(subject.to_internal_check.options).to eq subject.options.deep_symbolize_keys
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe ActiveValidation::Manifest, type: :active_record do
|
|
4
|
+
%i[update update_attribute update_attributes].each do |method|
|
|
5
|
+
it "raises on #{method}" do
|
|
6
|
+
expect { subject.send(method) }.to raise_error ActiveValidation::Errors::ImmutableError
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
context "with existed model" do
|
|
11
|
+
before do
|
|
12
|
+
define_const("Foo", superclass: ActiveRecord::Base)
|
|
13
|
+
define_const("FooValidator", superclass: ActiveModel::Validator)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "accepts nested attributes for checks" do
|
|
17
|
+
described_class.create name: "foo's manifest", version: 1, base_klass: "Foo", checks_attributes: [
|
|
18
|
+
attributes_for(:check_validates),
|
|
19
|
+
attributes_for(:check_validate),
|
|
20
|
+
attributes_for(:check_validates_with)
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
expect(described_class.count).to eq 1
|
|
24
|
+
expect(ActiveValidation::Check.count).to eq 3
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context "factories traits" do
|
|
29
|
+
%i[validate validates validates_with].each do |trait|
|
|
30
|
+
it "accept Factory trait #{trait} and build corresponding check" do
|
|
31
|
+
expect(build(:manifest, trait).checks.size).to eq 1
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context "#to_internal_manifest" do
|
|
37
|
+
let(:subject) { build :manifest, :validate }
|
|
38
|
+
|
|
39
|
+
it "produces right class" do
|
|
40
|
+
expect(subject.to_internal_manifest).to be_a ActiveValidation::Internal::Models::Manifest
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context "has value" do
|
|
44
|
+
%w[name version base_klass].each do |key|
|
|
45
|
+
it key.to_s do
|
|
46
|
+
expect(subject.to_internal_manifest.public_send(key)).to eq subject.public_send(key)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context "checks" do
|
|
51
|
+
subject { build(:manifest, :validate, :validates).to_internal_manifest.checks }
|
|
52
|
+
|
|
53
|
+
let!(:wrong) { build(:manifest, :validate) }
|
|
54
|
+
|
|
55
|
+
it { is_expected.to be_a Array }
|
|
56
|
+
it { is_expected.to all a_kind_of ActiveValidation::Internal::Models::Check }
|
|
57
|
+
it { is_expected.to have_attributes length: 2 }
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# At this moment there is only Active record Plugin, so it is
|
|
4
|
+
# used in the Readme files for examples.
|
|
5
|
+
|
|
6
|
+
# rubocop:disable RSpec/DescribeClass
|
|
7
|
+
# rubocop:disable RSpec/ExampleLength
|
|
8
|
+
describe "Readme" do
|
|
9
|
+
let(:manifest_with_checks) do
|
|
10
|
+
{
|
|
11
|
+
base_klass: "Foo", # Name of the Model Class
|
|
12
|
+
version: 1, # optional, by default use locked or latest version
|
|
13
|
+
name: "awesome-foo", # optional, some name for easier managing
|
|
14
|
+
|
|
15
|
+
# the syntax is the same with ActiveModel. For :validates_with and :validate `options` field is optional
|
|
16
|
+
checks_attributes: [
|
|
17
|
+
{ method_name: "validates", argument: "my_method", options: { presence: true } },
|
|
18
|
+
{ method_name: "validates_with", argument: "MyValidator" },
|
|
19
|
+
{ method_name: "validate", argument: "my_validation_method" }
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
let(:empty_manifest) do
|
|
25
|
+
{
|
|
26
|
+
base_klass: "Foo", # Name of the Model Class
|
|
27
|
+
checks_attributes: []
|
|
28
|
+
}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
before do
|
|
32
|
+
define_const("Foo", superclass: ActiveRecord::Base) do
|
|
33
|
+
active_validation
|
|
34
|
+
|
|
35
|
+
def my_method; end
|
|
36
|
+
|
|
37
|
+
def my_validation_method
|
|
38
|
+
errors.add(:base, "we'd called validation method")
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
define_const("MyValidator", superclass: ActiveModel::Validator) do
|
|
43
|
+
def validate(*); end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
define_const "Foo::Validations::V1"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "manifest manipulations" do
|
|
50
|
+
# This is how you can add the new manifest
|
|
51
|
+
|
|
52
|
+
Foo.active_validation.add_manifest(manifest_with_checks)
|
|
53
|
+
|
|
54
|
+
f = Foo.new
|
|
55
|
+
|
|
56
|
+
expect(f).not_to be_valid
|
|
57
|
+
expect(f.errors.messages).to have_key(:my_method)
|
|
58
|
+
expect(f.errors.messages).to have_key(:base)
|
|
59
|
+
|
|
60
|
+
# new manifest will be used for new records, while existed records
|
|
61
|
+
# continue using one of the previous versions
|
|
62
|
+
# the same result will be with `Foo.active_validation.add_manifest`
|
|
63
|
+
Foo.active_validation.add_manifest(empty_manifest)
|
|
64
|
+
|
|
65
|
+
expect(f).to be_valid
|
|
66
|
+
|
|
67
|
+
# get all manifests for current version
|
|
68
|
+
manifests = Foo.active_validation.find_manifests
|
|
69
|
+
|
|
70
|
+
expect(manifests.size).to eq 2
|
|
71
|
+
|
|
72
|
+
# we can specify version, if we want to
|
|
73
|
+
Foo.active_validation.find_manifests version: 42
|
|
74
|
+
|
|
75
|
+
# Get the latest manifest
|
|
76
|
+
manifest = Foo.active_validation.find_manifest
|
|
77
|
+
|
|
78
|
+
# we can con edit existed manifests, but we can easily
|
|
79
|
+
# create the new one based on the existed
|
|
80
|
+
Foo.active_validation.add_manifest(manifest.as_json.tap do |m|
|
|
81
|
+
m[:name] = "Something"
|
|
82
|
+
m[:id] = nil
|
|
83
|
+
end)
|
|
84
|
+
|
|
85
|
+
expect(Foo.active_validation.find_manifest.name).to eq "Something"
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
# rubocop:enable RSpec/DescribeClass
|
|
89
|
+
# rubocop:enable RSpec/ExampleLength
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe ActiveValidation::Registry do
|
|
4
|
+
subject { described_class.new("Great thing") }
|
|
5
|
+
|
|
6
|
+
let(:registered_object) { instance_double("registered object") }
|
|
7
|
+
let(:second_registered_object) { instance_double("second registered object") }
|
|
8
|
+
|
|
9
|
+
it { is_expected.to be_kind_of(Enumerable) }
|
|
10
|
+
|
|
11
|
+
it "finds a registered object" do
|
|
12
|
+
subject.register(:object_name, registered_object)
|
|
13
|
+
expect(subject.find(:object_name)).to eq registered_object
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "finds a registered object with square brackets" do
|
|
17
|
+
subject.register(:object_name, registered_object)
|
|
18
|
+
expect(subject[:object_name]).to eq registered_object
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "raises when an object cannot be found" do
|
|
22
|
+
expect { subject.find(:object_name) }
|
|
23
|
+
.to raise_error(KeyError, "Great thing not registered: \"object_name\"")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "adds and returns the object registered" do
|
|
27
|
+
expect(subject.register(:object_name, registered_object)).to eq registered_object
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "knows that an object is registered by symbol" do
|
|
31
|
+
subject.register(:object_name, registered_object)
|
|
32
|
+
expect(subject).to be_registered(:object_name)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "knows that an object is registered by string" do
|
|
36
|
+
subject.register(:object_name, registered_object)
|
|
37
|
+
expect(subject).to be_registered("object_name")
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "knows when an object is not registered" do
|
|
41
|
+
expect(subject).not_to be_registered("bogus")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "iterates registered objects" do
|
|
45
|
+
subject.register(:first_object, registered_object)
|
|
46
|
+
subject.register(:second_object, second_registered_object)
|
|
47
|
+
expect(subject.to_a).to eq [registered_object, second_registered_object]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "does not include duplicate objects with registered under different names" do
|
|
51
|
+
subject.register(:first_object, registered_object)
|
|
52
|
+
subject.register(:second_object, registered_object)
|
|
53
|
+
expect(subject.to_a).to eq [registered_object]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "clears registered objects" do
|
|
57
|
+
subject.register(:object_name, registered_object)
|
|
58
|
+
subject.clear
|
|
59
|
+
expect(subject.count).to be_zero
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "delete selected object" do
|
|
63
|
+
subject.register(:first_object, registered_object)
|
|
64
|
+
subject.register(:second_object, second_registered_object)
|
|
65
|
+
subject.delete :first_object
|
|
66
|
+
expect(subject.to_a).to eq [second_registered_object]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "store object key as symbol" do
|
|
70
|
+
subject.register("first object", registered_object)
|
|
71
|
+
subject.register(42, registered_object)
|
|
72
|
+
expect(subject).to be_registered(:"first object")
|
|
73
|
+
expect(subject).to be_registered(:"42")
|
|
74
|
+
expect(subject).not_to be_registered(:not_exist)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe ActiveValidation::Values::Base do
|
|
4
|
+
subject { described_class.new("42") }
|
|
5
|
+
|
|
6
|
+
context "Set" do
|
|
7
|
+
it("value") { expect(described_class.new(1).value).to eq 1 }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
context "Get" do
|
|
11
|
+
it("value") { expect(subject.value).to eq "42" }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context "raise" do
|
|
15
|
+
[nil, true, false].each do |el|
|
|
16
|
+
it("from #{el}") { expect { described_class.new(el).value }.to raise_error ArgumentError }
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "<=>" do
|
|
21
|
+
subject { %i[1 5 9 3 7].map { |n| described_class.new n } }
|
|
22
|
+
|
|
23
|
+
it("sort") { expect(subject.sort.map(&:to_s)).to eq %w[1 3 5 7 9] }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context "==" do
|
|
27
|
+
context "comarison instance vs value" do
|
|
28
|
+
let(:version1) { described_class.new 1 }
|
|
29
|
+
let(:another_version1) { described_class.new 1 }
|
|
30
|
+
|
|
31
|
+
it("is equal") { expect(version1).to eq another_version1 }
|
|
32
|
+
it("is not equal") { expect(version1).not_to eq subject }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context "comarison instance vs instance" do
|
|
36
|
+
let(:struct) { Struct.new(:foo) }
|
|
37
|
+
let(:version1) { described_class.new struct.new(foo: 42) }
|
|
38
|
+
let(:another_version1) { described_class.new struct.new(foo: 42) }
|
|
39
|
+
|
|
40
|
+
it("is equal") { expect(version1).to eq another_version1 }
|
|
41
|
+
it("is not equal") { expect(version1).not_to eq subject }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context "to_s" do
|
|
46
|
+
it("convert integer to string") { expect(described_class.new(1).to_s).to eq "1" }
|
|
47
|
+
it("convert symbol to string") { expect(described_class.new(:foo).to_s).to eq "foo" }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context "to_sym" do
|
|
51
|
+
it("convert string to symbol") { expect(described_class.new(:foo).to_sym).to eq :foo }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context "to_json" do
|
|
55
|
+
it("return only value") { expect(described_class.new(42).to_json).to eq "42" }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context "as_json" do
|
|
59
|
+
it("return only value") { expect(described_class.new(42).as_json).to eq 42 }
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe ActiveValidation::Values::MethodName do
|
|
4
|
+
context "::new" do
|
|
5
|
+
%w[validates validates_with validate].each do |name|
|
|
6
|
+
it("generate #{name}") { expect(described_class.new(name).value).to eq name }
|
|
7
|
+
it("is a String #{name}") { expect(described_class.new(name).value).to be_a String }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
context "raise" do
|
|
11
|
+
let(:error_class) { ActiveValidation::Errors::UnsupportedMethodError }
|
|
12
|
+
|
|
13
|
+
it("method is not allowed") { expect { described_class.new("bad").value }.to raise_error error_class }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe ActiveValidation::Values::Version do
|
|
4
|
+
context "::new" do
|
|
5
|
+
context 'with "V" prefix' do
|
|
6
|
+
it("from symbol") { expect(described_class.new(:V42).value).to eq 42 }
|
|
7
|
+
it("from string") { expect(described_class.new("V42").value).to eq 42 }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
context 'with out "V" prefix' do
|
|
11
|
+
it("from symbol") { expect(described_class.new(:'42').value).to eq 42 }
|
|
12
|
+
it("from string") { expect(described_class.new("42").value).to eq 42 }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
context "raise" do
|
|
16
|
+
[nil, true, false, "Foo1", "V55A"].each do |el|
|
|
17
|
+
it("from #{el}") { expect { described_class.new(el).value }.to raise_error ArgumentError }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it("set the value from integer") { expect(described_class.new(42).value).to eq 42 }
|
|
22
|
+
|
|
23
|
+
context "to_i" do
|
|
24
|
+
it("string to integer") { expect(described_class.new("42").to_i).to eq 42 }
|
|
25
|
+
it("symbol to integer") { expect(described_class.new("V42").to_i).to eq 42 }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context "to_json" do
|
|
29
|
+
it("return only value") { expect(described_class.new(42).to_json).to eq "42" }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
context "as_json" do
|
|
33
|
+
it("return only value") { expect(described_class.new(42).as_json).to eq 42 }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe ActiveValidation::Verifier do
|
|
4
|
+
subject { described_class.find_or_build "Foo" }
|
|
5
|
+
|
|
6
|
+
let(:model) { define_const("Foo") { attr_reader :manifest } }
|
|
7
|
+
|
|
8
|
+
context "class methods" do
|
|
9
|
+
subject { described_class }
|
|
10
|
+
|
|
11
|
+
it "return the global registry for verifier" do
|
|
12
|
+
expect(subject.registry).to eq ActiveValidation.config.verifiers_registry
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it { is_expected.to delegate(:find_or_build).to(:registry) }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
%i[failed_attempt_retry_time
|
|
19
|
+
enabled
|
|
20
|
+
observer
|
|
21
|
+
validations_module_name
|
|
22
|
+
base_klass
|
|
23
|
+
orm_adapter
|
|
24
|
+
manifest_name_formatter
|
|
25
|
+
manifest].each { |m| it { is_expected.to have_attr_reader m } }
|
|
26
|
+
|
|
27
|
+
it { is_expected.to delegate(:install).to(:observer) }
|
|
28
|
+
|
|
29
|
+
context "with fake registry" do
|
|
30
|
+
subject { described_class.find_or_build "Bar" }
|
|
31
|
+
|
|
32
|
+
let!(:bar) do
|
|
33
|
+
define_const "Bar" do
|
|
34
|
+
include ActiveValidation::ModelExtensionBase
|
|
35
|
+
active_validation
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
include_examples "verifiers registry"
|
|
40
|
+
|
|
41
|
+
context "orm methods" do
|
|
42
|
+
context "#add_manifest" do
|
|
43
|
+
before do
|
|
44
|
+
allow(subject.orm_adapter).to receive(:add_manifest)
|
|
45
|
+
define_const "Bar::Validations::V17"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "calculate name and set default klass & version" do
|
|
49
|
+
subject.add_manifest
|
|
50
|
+
defaults = { base_klass: bar.to_s,
|
|
51
|
+
version: ActiveValidation::Values::Version.new(17),
|
|
52
|
+
name: "Manifest for Bar" }
|
|
53
|
+
expect(subject.orm_adapter).to have_received(:add_manifest).with(defaults)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context "#find_manifest" do
|
|
58
|
+
before { allow(subject.orm_adapter).to receive(:find_manifest) }
|
|
59
|
+
|
|
60
|
+
it "set defaults" do
|
|
61
|
+
subject.find_manifest
|
|
62
|
+
defaults = { base_klass: bar.to_s }
|
|
63
|
+
expect(subject.orm_adapter).to have_received(:find_manifest).with(defaults)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context "#find_manifests" do
|
|
68
|
+
before { allow(subject.orm_adapter).to receive(:find_manifests) }
|
|
69
|
+
|
|
70
|
+
it "set defaults" do
|
|
71
|
+
subject.find_manifests
|
|
72
|
+
defaults = { base_klass: bar.to_s }
|
|
73
|
+
expect(subject.orm_adapter).to have_received(:find_manifests).with(defaults)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
context "#versions" do
|
|
79
|
+
before do
|
|
80
|
+
define_consts "Bar::Validations::V1",
|
|
81
|
+
"Bar::Validations::V2",
|
|
82
|
+
"Bar::Validations::V23",
|
|
83
|
+
"Bar::Validations::V42"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "returns correct versions in asc order" do
|
|
87
|
+
expect(subject.versions.map(&:to_i)).to eq [1, 2, 23, 42]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "returns only value version type" do
|
|
91
|
+
expect(subject.versions).to all be_an ActiveValidation::Values::Version
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
context "#version" do
|
|
96
|
+
before do
|
|
97
|
+
define_consts "Bar::Validations::V300",
|
|
98
|
+
"Bar::Validations::V301",
|
|
99
|
+
"Bar::Validations::V302"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "use latest version by default" do
|
|
103
|
+
expect(subject.version).to eq ActiveValidation::Values::Version.new(302)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "set/gets version" do
|
|
107
|
+
subject.version = :V300
|
|
108
|
+
expect(subject.version).to eq ActiveValidation::Values::Version.new(300)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
context "#base_class" do
|
|
113
|
+
it "return Class if base_klass as String given" do
|
|
114
|
+
expect(described_class.new(model.name).base_class).to eq model
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "return Class if base_klass as Class given" do
|
|
118
|
+
expect(described_class.new(model).base_class).to eq model
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
context "#descendants_with_active_validation" do
|
|
123
|
+
subject { described_class.find_or_build(foo_descendant3).descendants_with_active_validation }
|
|
124
|
+
|
|
125
|
+
let!(:should_not_be_in_the_list) { define_const "ShouldNotBeInTheList" }
|
|
126
|
+
let!(:baz) do
|
|
127
|
+
define_const("Baz", superclass: should_not_be_in_the_list) do
|
|
128
|
+
include ActiveValidation::ModelExtensionBase
|
|
129
|
+
active_validation
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
let(:foo) do
|
|
134
|
+
define_const("Foo", superclass: should_not_be_in_the_list) do
|
|
135
|
+
include ActiveValidation::ModelExtensionBase
|
|
136
|
+
active_validation
|
|
137
|
+
attr_reader :manifest
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
let(:foo_descendant1) { define_const("FooDescendant1", superclass: foo) { attr_reader :manifest } }
|
|
142
|
+
let(:foo_descendant2) { define_const("FooDescendant2", superclass: foo_descendant1) { attr_reader :manifest } }
|
|
143
|
+
let(:foo_descendant3) { define_const("FooDescendant3", superclass: foo_descendant2) }
|
|
144
|
+
|
|
145
|
+
it "returns only Foo based constants" do
|
|
146
|
+
expect(subject).to match [foo_descendant2, foo_descendant1, foo]
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it "returns empty array for foo" do
|
|
150
|
+
expect(described_class.find_or_build(foo).descendants_with_active_validation).to be_empty
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
context "#current_manifest" do
|
|
155
|
+
let(:manifest) { ActiveValidation::Internal::Models::Manifest.new version: 1, base_klass: "Bar" }
|
|
156
|
+
|
|
157
|
+
it "return manifest, if it was set" do
|
|
158
|
+
subject.manifest = manifest
|
|
159
|
+
expect(subject.current_manifest).to eq manifest
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it "call #find_manifests if manifest is not set" do
|
|
163
|
+
allow(subject).to receive(:find_manifests).and_return([]) # rubocop:disable RSpec/SubjectStub
|
|
164
|
+
define_consts "Bar::Validations::V11"
|
|
165
|
+
expect(subject.current_manifest).to be_nil
|
|
166
|
+
expect(subject).to have_received(:find_manifests)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
context "#initialize" do
|
|
171
|
+
it "yield given block" do
|
|
172
|
+
expect { |b| described_class.find_or_build(bar.name, &b) }.to yield_control
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it "register self in global registry" do
|
|
176
|
+
subject
|
|
177
|
+
expect(registry).to be_registered(bar.to_s)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it "invoke default config" do
|
|
181
|
+
allow(ActiveValidation.config.verifier_defaults).to receive(:call)
|
|
182
|
+
expect(ActiveValidation.config.verifier_defaults).to have_received(:call).with(subject)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
context "#enabled" do
|
|
188
|
+
context "true" do
|
|
189
|
+
subject { described_class.find_or_build("Foo") { |c| c.enabled = true }.enabled? }
|
|
190
|
+
|
|
191
|
+
it { is_expected.to be true }
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
context "false" do
|
|
195
|
+
subject { described_class.find_or_build("Foo") { |c| c.enabled = false }.enabled? }
|
|
196
|
+
|
|
197
|
+
it { is_expected.to be false }
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
context "#install!" do
|
|
202
|
+
let!(:bar) { define_const("Bar", superclass: model) { attr_reader :manifest } }
|
|
203
|
+
|
|
204
|
+
before do
|
|
205
|
+
model.include ActiveValidation::ModelExtensionBase
|
|
206
|
+
allow(Foo.active_validation).to receive(:install)
|
|
207
|
+
allow(Bar.active_validation).to receive(:install)
|
|
208
|
+
described_class.find_or_build("Bar").install!
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it("installs on Foo") { expect(Foo.active_validation).to have_received(:install) }
|
|
212
|
+
it("installs on Bar") { expect(Bar.active_validation).to have_received(:install) }
|
|
213
|
+
end
|
|
214
|
+
end
|