activevalidation 0.1.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
using ActiveValidation::Internal::Models::Concerns::ToInternal::Check
|
4
|
+
|
5
|
+
module ActiveValidation
|
6
|
+
module Internal
|
7
|
+
module Models
|
8
|
+
class Manifest
|
9
|
+
class Installer
|
10
|
+
attr_reader :base_class, :installed_callbacks, :checks, :context
|
11
|
+
|
12
|
+
def initialize(base_class:, checks: [], context:)
|
13
|
+
@base_class = base_class
|
14
|
+
@checks = checks
|
15
|
+
@context = context
|
16
|
+
@installed_callbacks = []
|
17
|
+
end
|
18
|
+
|
19
|
+
# Add all checks (validations) to base_class
|
20
|
+
#
|
21
|
+
# @note we have to use the hack with
|
22
|
+
# `callbacks_chain.each.to_a # => chain` since `chain` method is
|
23
|
+
# protected.
|
24
|
+
#
|
25
|
+
# @return [TrueClass]
|
26
|
+
def install
|
27
|
+
@installed_callbacks = chain_mutex.synchronize do
|
28
|
+
before = callbacks_chain_elements
|
29
|
+
checks.each { |check| base_class.public_send(*check.to_validation_arguments(context: context)) }
|
30
|
+
callbacks_chain_elements - before
|
31
|
+
end
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
# Remove all checks (validations) from base_class
|
36
|
+
#
|
37
|
+
# we can not use ActiveSupport provided methods, since we already have
|
38
|
+
# our installed callbacks.
|
39
|
+
#
|
40
|
+
# @return [FalseClass]
|
41
|
+
def uninstall
|
42
|
+
installed_validators = installed_callbacks.map(&:filter).select { |f| f.is_a? ActiveModel::Validator }
|
43
|
+
|
44
|
+
([base_class] + ActiveSupport::DescendantsTracker.descendants(base_class)).reverse_each do |target|
|
45
|
+
uninstall! target: target, installed_validators: installed_validators
|
46
|
+
end
|
47
|
+
installed_callbacks.clear
|
48
|
+
false
|
49
|
+
end
|
50
|
+
|
51
|
+
def callbacks_chain
|
52
|
+
base_class._validate_callbacks
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
# We cannot call `chain` method directly, so we have to use this hack
|
58
|
+
#
|
59
|
+
# @return [Array<ActiveSupport::Callbacks>]
|
60
|
+
def callbacks_chain_elements
|
61
|
+
callbacks_chain.each.to_a
|
62
|
+
end
|
63
|
+
|
64
|
+
# Mutex from ActiveSupport::Callbacks::CallbackChain for `base_class`
|
65
|
+
#
|
66
|
+
# @return [Mutex]
|
67
|
+
def chain_mutex
|
68
|
+
callbacks_chain.instance_variable_get(:@mutex)
|
69
|
+
end
|
70
|
+
|
71
|
+
def uninstall!(target:, installed_validators:)
|
72
|
+
chain = target._validate_callbacks
|
73
|
+
|
74
|
+
chain.instance_variable_get(:@mutex).synchronize do
|
75
|
+
target._validators
|
76
|
+
.each_value { |v| v.reject! { |el| installed_validators.include?(el) } }
|
77
|
+
.delete_if { |_, v| v.empty? }
|
78
|
+
|
79
|
+
installed_callbacks.each { |callback| chain.delete(callback) }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveValidation
|
4
|
+
module Internal
|
5
|
+
module Observers
|
6
|
+
class Manifest
|
7
|
+
DISABLED_VERIFIER = :verifier_is_not_enabled
|
8
|
+
RECENT_FAILURE = :it_was_failed_too_recently
|
9
|
+
NOT_FOUND = :not_found
|
10
|
+
ALREADY_INSTALLED = :already_installed
|
11
|
+
INSTALLED = :installed
|
12
|
+
UNINSTALLED = :uninstalled
|
13
|
+
|
14
|
+
attr_reader :verifier, :installed_manifests, :last_failed_attempt_time
|
15
|
+
|
16
|
+
delegate :manifest, :failed_attempt_retry_time, :enabled?, to: :verifier
|
17
|
+
|
18
|
+
def initialize(verifier)
|
19
|
+
@verifier = verifier
|
20
|
+
@installed_manifests = Concurrent::Set.new
|
21
|
+
@lock = Concurrent::ReadWriteLock.new
|
22
|
+
@last_failed_attempt_time = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
# Install manifest and store the result. Load priority:
|
26
|
+
# * `manifest_id` from the arguments
|
27
|
+
# * `verifier.manifest` - defined by user in verifier block
|
28
|
+
# * `current_manifest` - the latest manifest with current version
|
29
|
+
#
|
30
|
+
# The process will be skipped if:
|
31
|
+
# - `verifier` not `enabled?`
|
32
|
+
# - The last failed attempt was too recent.
|
33
|
+
#
|
34
|
+
# @return Symbol
|
35
|
+
def install(manifest_id: nil)
|
36
|
+
return DISABLED_VERIFIER unless enabled?
|
37
|
+
return RECENT_FAILURE if attempt_to_was_failed_recently?
|
38
|
+
|
39
|
+
found = lock.with_read_lock { find(manifest_id: manifest_id) } || current_manifest
|
40
|
+
return NOT_FOUND unless found
|
41
|
+
return ALREADY_INSTALLED if found.installed?
|
42
|
+
|
43
|
+
install! internal_manifest: found
|
44
|
+
end
|
45
|
+
|
46
|
+
# Uninstall the manifest.
|
47
|
+
#
|
48
|
+
# @return Symbol
|
49
|
+
def uninstall(manifest_id:)
|
50
|
+
lock.with_write_lock do
|
51
|
+
internal_manifest = find(manifest_id: manifest_id)
|
52
|
+
return NOT_FOUND unless internal_manifest&.installed?
|
53
|
+
|
54
|
+
internal_manifest.uninstall
|
55
|
+
installed_manifests.delete internal_manifest
|
56
|
+
end
|
57
|
+
UNINSTALLED
|
58
|
+
end
|
59
|
+
|
60
|
+
# We omit the error and only save the error time to prevent
|
61
|
+
# DB flooding, when there is no any manifest.
|
62
|
+
#
|
63
|
+
# We do not know all possible errors so we can not be more
|
64
|
+
# specific here.
|
65
|
+
#
|
66
|
+
# @return [Internal::Manifest]
|
67
|
+
def current_manifest
|
68
|
+
verifier.current_manifest.to_internal_manifest
|
69
|
+
rescue StandardError => _e
|
70
|
+
@last_failed_attempt_time = Time.now
|
71
|
+
nil
|
72
|
+
end
|
73
|
+
|
74
|
+
# We need this method for been able to restore manifest lookup
|
75
|
+
#
|
76
|
+
# @return nil
|
77
|
+
def reset_last_failed_attempt_time
|
78
|
+
@last_failed_attempt_time = nil
|
79
|
+
end
|
80
|
+
|
81
|
+
# The actual install process
|
82
|
+
#
|
83
|
+
# @return Symbol
|
84
|
+
def install!(internal_manifest:)
|
85
|
+
lock.with_write_lock do
|
86
|
+
return ALREADY_INSTALLED if find(manifest_id: internal_manifest.id)&.installed?
|
87
|
+
|
88
|
+
internal_manifest.install
|
89
|
+
installed_manifests << internal_manifest
|
90
|
+
end
|
91
|
+
INSTALLED
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
attr_reader :lock
|
97
|
+
|
98
|
+
def find(manifest_id: nil)
|
99
|
+
return unless manifest_id
|
100
|
+
|
101
|
+
@installed_manifests.detect do |manifest|
|
102
|
+
manifest.id == manifest_id
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def attempt_to_was_failed_recently?
|
107
|
+
return unless last_failed_attempt_time
|
108
|
+
|
109
|
+
Time.now < @last_failed_attempt_time + failed_attempt_retry_time
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveValidation
|
4
|
+
module ModelExtensionBase
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
module ClassMethods
|
7
|
+
# This is entry point, which setup or return existed Verifier.
|
8
|
+
#
|
9
|
+
# @return Verifier
|
10
|
+
def active_validation(&block)
|
11
|
+
register_active_validation_relations unless ActiveValidation::Verifier.registry.registered? self
|
12
|
+
::ActiveValidation::Verifier.find_or_build self, &block
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# Invoke the checks that validations are in place. Should be overwritten in ORM
|
18
|
+
# adapter
|
19
|
+
#
|
20
|
+
# @return nil
|
21
|
+
def register_active_validation_relations; end
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
# We need to be sure, that all validation call backs are in place before validation
|
27
|
+
#
|
28
|
+
# @return nil
|
29
|
+
def process_active_validation
|
30
|
+
::ActiveValidation::Verifier.find_or_build(self.class).install!(manifest_id: manifest_id)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveValidation
|
4
|
+
module OrmPlugins
|
5
|
+
module ActiveRecordPlugin
|
6
|
+
class Adapter < ActiveValidation::BaseAdapter
|
7
|
+
loading_paths << "models"
|
8
|
+
loading_paths << "types"
|
9
|
+
loading_paths << "internals"
|
10
|
+
loading_paths << "model_extension"
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
setup unless self.class.initialised
|
14
|
+
self.class.initialised = true
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [true]
|
18
|
+
def setup
|
19
|
+
return installer if defined?(::ActiveRecord::Base)
|
20
|
+
|
21
|
+
::ActiveSupport.on_load(:active_record_adapter, &method(:installer))
|
22
|
+
end
|
23
|
+
|
24
|
+
# @see BaseAdapter
|
25
|
+
def add_manifest(manifest)
|
26
|
+
Manifest.create manifest.as_json(checks: { only: %i[type argument options], as: :checks_attributes })
|
27
|
+
manifest
|
28
|
+
end
|
29
|
+
|
30
|
+
# @see BaseAdapter
|
31
|
+
def find_manifests(wheres)
|
32
|
+
search(wheres)
|
33
|
+
end
|
34
|
+
|
35
|
+
# @see BaseAdapter
|
36
|
+
def find_manifest(wheres)
|
37
|
+
search(wheres, &:first!)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# @api internal
|
43
|
+
def search(wheres)
|
44
|
+
relation = Manifest.includes(:checks).where(wheres).order(created_at: :desc, id: :desc)
|
45
|
+
relation = yield relation if block_given?
|
46
|
+
relation.is_a?(ActiveRecord::Base) ? relation.to_internal_manifest : relation.map(&:to_internal_manifest)
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [true]
|
50
|
+
def installer
|
51
|
+
ActiveValidation::OrmPlugins::ActiveRecordPlugin::Adapter.loader
|
52
|
+
ActiveValidation::Internal::Models::Check.include(ActiveValidation::InternalModelExtensions::Check)
|
53
|
+
::ActiveRecord::Base.include ActiveValidation::ActiveRecordModelExtension
|
54
|
+
true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveValidation
|
4
|
+
module ActiveRecordModelExtension
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
include ModelExtensionBase
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
private
|
10
|
+
|
11
|
+
def register_active_validation_relations
|
12
|
+
before_validation :process_active_validation
|
13
|
+
|
14
|
+
belongs_to :manifest, class_name: "::ActiveValidation::Manifest", dependent: :destroy
|
15
|
+
|
16
|
+
ActiveValidation::Manifest.has_many realtion_plural_name
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def realtion_plural_name
|
21
|
+
name.underscore.pluralize.to_sym
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveValidation
|
4
|
+
class Check < ActiveRecord::Base
|
5
|
+
prepend ActiveValidation::Concerns::ProtectFromMutableInstanceMethods
|
6
|
+
|
7
|
+
serialize :options
|
8
|
+
|
9
|
+
self.table_name = :active_validation_checks
|
10
|
+
self.store_full_sti_class = false
|
11
|
+
|
12
|
+
belongs_to :manifest, inverse_of: :checks
|
13
|
+
|
14
|
+
validates :argument, presence: true
|
15
|
+
|
16
|
+
def method_name
|
17
|
+
raise NotImplementedError, "abstract" unless self.class < Check
|
18
|
+
|
19
|
+
self.class.name.demodulize.sub(/Method\z/, "").underscore
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_name=(other)
|
23
|
+
self.type = other.camelcase + "Method"
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_internal_check
|
27
|
+
json_options = { methods: %i[method_name], root: false }
|
28
|
+
ActiveValidation::Internal::Models::Check.new as_json(json_options).to_options!
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveValidation
|
4
|
+
class Check < ActiveRecord::Base
|
5
|
+
module Concerns
|
6
|
+
module MethodMustBeAllowed
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
validate :method_must_be_allowed
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def method_must_be_allowed
|
16
|
+
verify_options
|
17
|
+
verify_argument
|
18
|
+
end
|
19
|
+
|
20
|
+
def verify_options
|
21
|
+
return unless options
|
22
|
+
|
23
|
+
danger_values = options.slice([:if, :unless, "if", "unless"]).values
|
24
|
+
return if (danger_values & restricted_instance_methods).empty?
|
25
|
+
|
26
|
+
errors.add :options, "Options contain dangerous checks"
|
27
|
+
end
|
28
|
+
|
29
|
+
def verify_argument
|
30
|
+
return unless argument && manifest.try(:base_klass)
|
31
|
+
return unless restricted_instance_methods.include?(argument.to_sym)
|
32
|
+
|
33
|
+
errors.add :argument, "method #{argument} is restricted for usage in validation"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveValidation
|
4
|
+
class Check < ActiveRecord::Base
|
5
|
+
class ValidatesWithMethod < Check
|
6
|
+
validate :validator_must_be_defined
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def validator_must_be_defined
|
11
|
+
return if argument.blank?
|
12
|
+
|
13
|
+
argument.constantize.is_a? ActiveModel::Validator
|
14
|
+
rescue NameError
|
15
|
+
errors.add :argument, "Validator not exist"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|