Class: RuboCop::Cop::RSpec::InverseOfMatcher
- Inherits:
-
Base
- Object
- Base
- RuboCop::Cop::RSpec::InverseOfMatcher
- Defined in:
- lib/rubocop/cop/rspec/inverse_of_matcher.rb
Overview
Ensures that RSpec association specs handle ‘.inverse_of` correctly depending on whether the model is a root (directly < ApplicationRecord) or a subclass (STI).
Rules:
-
Root models (direct superclass = ApplicationRecord) must include ‘.inverse_of`.
-
Subclasses (STI, superclass != ApplicationRecord but still inherit indirectly) must NOT include ‘.inverse_of`.
-
Associations marked as polymorphic or through are ignored.
-
Non-ActiveRecord classes are ignored.
Constant Summary collapse
- MSG_MISSING_INVERSE =
'Root models must include `.inverse_of` in association specs.'- MSG_FORBIDDEN_INVERSE =
'Subclasses must NOT include `.inverse_of` in specs (it belongs to the parent).'
Class Method Summary collapse
Instance Method Summary collapse
Class Method Details
.default_configuration ⇒ Object
22 23 24 25 26 |
# File 'lib/rubocop/cop/rspec/inverse_of_matcher.rb', line 22 def self.default_configuration super.merge( 'Include' => ['spec/models/**/*_spec.rb'] ) end |
Instance Method Details
#on_send(node) ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/rubocop/cop/rspec/inverse_of_matcher.rb', line 28 def on_send(node) return unless node.method?(:belong_to) # Skip polymorphic or through associations return if chain_has_option?(node, :polymorphic) return if chain_has_option?(node, :through) model_name = model_class_from_spec return unless model_name classification = classify_model(model_name) return if classification == :non_ar # ignore non-ActiveRecord classes if classification == :root add_offense(node.loc.selector, message: MSG_MISSING_INVERSE) unless chain_has_inverse_of?(node) elsif classification == :subclass add_offense(node.loc.selector, message: MSG_FORBIDDEN_INVERSE) if chain_has_inverse_of?(node) end rescue StandardError => e source_name = if processed_source && processed_source.buffer processed_source.file_path else 'unknown' end warn "RSpec/InverseOfMatcher failed on #{source_name}: #{e.}" end |