Class: RuboCop::Cop::Gusto::PolymorphicTypeValidation
- Inherits:
-
Base
- Object
- Base
- RuboCop::Cop::Gusto::PolymorphicTypeValidation
- Defined in:
- lib/rubocop/cop/gusto/polymorphic_type_validation.rb
Constant Summary collapse
- RESTRICT_ON_SEND =
%i(belongs_to validates polymorphic_methods_for).freeze
- MSG =
<<~MESSAGE Polymorphic relations must validate their corresponding type field with "validates .. inclusion: { in: .. }", or using polymorphic_methods_for Example: # bad belongs_to :subscription_detail, polymorphic: true # good VALID_TYPES = T.let([LidiSubscriptionDetail.polymorphic_name, LegacyActiveBenefits::VoluntaryLifeSubscriptionDetail.polymorphic_name].freeze, T::Array[String]) belongs_to :subscription_detail, polymorphic: true validates :subscription_detail_type, presence: true, inclusion: { in: VALID_TYPES } # also good (in ZP/HI, at least) include PolymorphicCallable VALID_TYPES = T.let([LidiSubscriptionDetail.polymorphic_name, LegacyActiveBenefits::VoluntaryLifeSubscriptionDetail.polymorphic_name].freeze, T::Array[String]) belongs_to :subscription_detail, polymorphic: true polymorphic_methods_for :subscription_detail, VALID_TYPES MESSAGE
- ALLOW_BLANK_MSG =
"Polymorphic type validations cannot use allow_blank: true"
Instance Method Summary collapse
- #allow_blank?(node) ⇒ Object
- #inclusion_in?(node) ⇒ Object
- #on_send(node) ⇒ Object
- #polymorphic_methods_for?(node) ⇒ Object
- #polymorphic_relation?(node) ⇒ Object
- #type_validation?(node) ⇒ Object
Instance Method Details
#allow_blank?(node) ⇒ Object
54 55 56 |
# File 'lib/rubocop/cop/gusto/polymorphic_type_validation.rb', line 54 def_node_matcher :allow_blank?, <<~PATTERN (pair (sym :allow_blank) (true)) PATTERN |
#inclusion_in?(node) ⇒ Object
44 45 46 |
# File 'lib/rubocop/cop/gusto/polymorphic_type_validation.rb', line 44 def_node_matcher :inclusion_in?, <<~PATTERN (pair (sym :inclusion) (hash <(pair (sym :in) _) ...>)) PATTERN |
#on_send(node) ⇒ Object
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 |
# File 'lib/rubocop/cop/gusto/polymorphic_type_validation.rb', line 58 def on_send(node) return unless polymorphic_relation?(node) relation_name = node.first_argument.value type_field = :"#{relation_name}_type" # Look for either a validation of the type field or polymorphic_methods_for has_validation = false has_allow_blank = false node.parent.each_node(:send) do |validation_node| if type_validation?(validation_node) && validation_node.first_argument.value == type_field has_validation = true # Check for allow_blank in the validation options validation_node.last_argument.each_node(:pair) do |pair_node| has_allow_blank = true if allow_blank?(pair_node) end elsif polymorphic_methods_for?(validation_node) && validation_node.first_argument.value == relation_name has_validation = true end end if has_allow_blank add_offense(node, message: ALLOW_BLANK_MSG) elsif !has_validation add_offense(node) end end |
#polymorphic_methods_for?(node) ⇒ Object
49 50 51 |
# File 'lib/rubocop/cop/gusto/polymorphic_type_validation.rb', line 49 def_node_matcher :polymorphic_methods_for?, <<~PATTERN (send nil? :polymorphic_methods_for (sym _) _) PATTERN |
#polymorphic_relation?(node) ⇒ Object
34 35 36 |
# File 'lib/rubocop/cop/gusto/polymorphic_type_validation.rb', line 34 def_node_matcher :polymorphic_relation?, <<~PATTERN (send nil? :belongs_to _ (hash <(pair (sym :polymorphic) (true)) ...>)) PATTERN |
#type_validation?(node) ⇒ Object
39 40 41 |
# File 'lib/rubocop/cop/gusto/polymorphic_type_validation.rb', line 39 def_node_matcher :type_validation?, <<~PATTERN (send nil? :validates (sym _) (hash <#inclusion_in? ...>)) PATTERN |