Class: RuboCop::Cop::Seams::NoCrossEngineModelAccess

Inherits:
Base
  • Object
show all
Defined in:
lib/seams/cops/no_cross_engine_model_access.rb

Overview

Flags references to another engine’s data classes from inside an engine. Engines should communicate via events or via explicitly-exposed concerns — never by reaching into another engine’s data layer.

Configured per-engine via the ‘OwnEngine`, `OtherEngines`, and `ExposedConcerns` options inside the engine’s own .rubocop.yml.

The cop deliberately ignores Rails framework constants that every engine exposes (‘Engine`, `VERSION`, `ApplicationController`, `ApplicationRecord`, `ApplicationJob`, `ApplicationMailer`) and any class whose name ends in one of the configured suffixes (`Controller`, `Job`, `Mailer`, `Helper`, `Component`, `Engine`). Concerns (`Billing::Billable`, `Billing::Concerns::Billable`) are exempt when listed in `ExposedConcerns`.

‘<Engine>::Current` is also exempt by design: every engine ships its own `ActiveSupport::CurrentAttributes` namespace (`Auth::Current`, `Accounts::Current`, `Teams::Current`, etc.) and these per-request state holders are intentionally readable from anywhere in the host. Treating them as boundary-violations would force every cross-engine read of per-request identity / account / team to go through a host-defined shim, which defeats the purpose of `CurrentAttributes` as a shared per-request bus. The exception is documented in `doc/CURRENT_ATTRIBUTES.md`.

Constant Summary collapse

MSG =
"Engine `%<own>s` must not access `%<const>s` directly. " \
"Use an event or a %<other>s-exposed concern instead."
DEFAULT_IGNORED_LEAF_NAMES =
%w[
  Engine
  VERSION
  ApplicationController
  ApplicationRecord
  ApplicationJob
  ApplicationMailer
  ApplicationHelper
  ApplicationCable
  Routes
  Current
].freeze
DEFAULT_IGNORED_LEAF_SUFFIXES =
%w[
  Controller
  Job
  Mailer
  Helper
  Component
  Channel
  Engine
].freeze

Instance Method Summary collapse

Instance Method Details

#on_const(node) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/seams/cops/no_cross_engine_model_access.rb', line 60

def on_const(node)
  return unless flaggable?(node)

  full_name = node.const_name.to_s
  top_level = full_name.split("::").first

  assert_own_engine_configured!

  add_offense(
    node,
    message: format(MSG, own: own_engine, const: full_name, other: top_level)
  )
end