Class: Gitlab::Utils::DelegatorOverride::Validator
- Inherits:
-
Object
- Object
- Gitlab::Utils::DelegatorOverride::Validator
- Defined in:
- lib/gitlab/utils/delegator_override/validator.rb
Constant Summary collapse
- UnexpectedDelegatorOverrideError =
Class.new(StandardError)
- OVERRIDE_ERROR_MESSAGE =
<<~EOS We've detected that the delegator is overriding a specific method(s) on the target class. Please make sure if it's intentional and handle this error accordingly. See https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/presenters/README.md#validate-accidental-overrides for more information. EOS
Instance Attribute Summary collapse
-
#delegator_class ⇒ Object
readonly
Returns the value of attribute delegator_class.
-
#target_classes ⇒ Object
readonly
Returns the value of attribute target_classes.
Instance Method Summary collapse
- #add_allowlist(names) ⇒ Object
- #add_target(target_class) ⇒ Object
- #allowed_method_names ⇒ Object
-
#expand_on_ancestors(validators) ⇒ Object
This will make sure allowlist we put into ancestors are all included.
-
#initialize(delegator_class) ⇒ Validator
constructor
A new instance of Validator.
- #validate_overrides! ⇒ Object
Constructor Details
#initialize(delegator_class) ⇒ Validator
Returns a new instance of Validator.
17 18 19 20 |
# File 'lib/gitlab/utils/delegator_override/validator.rb', line 17 def initialize(delegator_class) @delegator_class = delegator_class @target_classes = [] end |
Instance Attribute Details
#delegator_class ⇒ Object (readonly)
Returns the value of attribute delegator_class.
9 10 11 |
# File 'lib/gitlab/utils/delegator_override/validator.rb', line 9 def delegator_class @delegator_class end |
#target_classes ⇒ Object (readonly)
Returns the value of attribute target_classes.
9 10 11 |
# File 'lib/gitlab/utils/delegator_override/validator.rb', line 9 def target_classes @target_classes end |
Instance Method Details
#add_allowlist(names) ⇒ Object
22 23 24 |
# File 'lib/gitlab/utils/delegator_override/validator.rb', line 22 def add_allowlist(names) allowed_method_names.concat(names) end |
#add_target(target_class) ⇒ Object
30 31 32 33 34 35 36 37 38 |
# File 'lib/gitlab/utils/delegator_override/validator.rb', line 30 def add_target(target_class) return unless target_class @target_classes << target_class # Also include all descendants inheriting from the target, # to make sure we catch methods that are only defined in some of them. @target_classes += target_class.descendants end |
#allowed_method_names ⇒ Object
26 27 28 |
# File 'lib/gitlab/utils/delegator_override/validator.rb', line 26 def allowed_method_names @allowed_method_names ||= [] end |
#expand_on_ancestors(validators) ⇒ Object
This will make sure allowlist we put into ancestors are all included
41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/gitlab/utils/delegator_override/validator.rb', line 41 def (validators) delegator_class.ancestors.each do |ancestor| next if delegator_class == ancestor # ancestor includes itself validator_ancestor = validators[ancestor] next unless validator_ancestor add_allowlist(validator_ancestor.allowed_method_names) end end |
#validate_overrides! ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/gitlab/utils/delegator_override/validator.rb', line 53 def validate_overrides! return if target_classes.empty? errors = [] # Workaround to fully load the instance methods in the target class. # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69823#note_678887402 begin target_classes.map(&:new) rescue ArgumentError # Some models might raise ArgumentError here, but it's fine in this case, # because this is enough to force ActiveRecord to generate the methods we # need to verify, so it's safe to ignore it. end (delegator_class.instance_methods - allowlist).each do |method_name| target_classes.each do |target_class| next unless target_class.method_defined?(method_name) errors << generate_error(method_name, target_class, delegator_class) end end return if errors.empty? details = errors.map { |error| "- #{error}" }.join("\n") raise UnexpectedDelegatorOverrideError, <<~TEXT #{OVERRIDE_ERROR_MESSAGE} Here are the conflict details. #{details} TEXT end |