Class: DevDoc::Test::Lints::DomainClassBaseChecker
- Inherits:
-
Object
- Object
- DevDoc::Test::Lints::DomainClassBaseChecker
- Defined in:
- lib/dev_doc/test/lints/domain_class_base.rb
Overview
Runtime check: every CLASS defined by a file under app/models/
(excluding concerns/) must descend from one of the project's domain
base classes. Runs with the app loaded, so real ancestry is checked —
intermediate family bases and indirect inheritance resolve correctly,
which is exactly what a per-file static cop cannot do.
Wrapped by the Minitest module DomainClassBase below — see that
module for the rationale.
Constant Summary collapse
- DEFAULT_BASE_CLASS_NAMES =
The three-way rule (best_practices/backend/en/03_model.md item 9): persisted -> ApplicationRecord; table-less but form-backed -> ApplicationModel; plain domain logic -> PlainModel.
%w[ApplicationRecord ApplicationModel PlainModel].freeze
Instance Method Summary collapse
-
#initialize(project_root, base_class_names: DEFAULT_BASE_CLASS_NAMES, allowed_paths: []) ⇒ DomainClassBaseChecker
constructor
A new instance of DomainClassBaseChecker.
-
#offenders ⇒ Object
Returns an Array
of offender descriptions, or []when every model class descends from an allowed base.
Constructor Details
#initialize(project_root, base_class_names: DEFAULT_BASE_CLASS_NAMES, allowed_paths: []) ⇒ DomainClassBaseChecker
Returns a new instance of DomainClassBaseChecker.
20 21 22 23 24 |
# File 'lib/dev_doc/test/lints/domain_class_base.rb', line 20 def initialize(project_root, base_class_names: DEFAULT_BASE_CLASS_NAMES, allowed_paths: []) @project_root = Pathname(project_root) @base_class_names = base_class_names @allowed_paths = allowed_paths end |
Instance Method Details
#offenders ⇒ Object
Returns an Array[] when
every model class descends from an allowed base. Modules are skipped:
the three-way rule classifies CLASSES — namespaces, function-bag
modules, and concerns carry no instance state to classify.
30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/dev_doc/test/lints/domain_class_base.rb', line 30 def offenders bases = @base_class_names.map(&:constantize) model_files.filter_map do |path| constant = constant_for(path) next if constant.nil? # module or namespace-only file next if bases.any? { |base| constant <= base } " #{relative(path)}: #{constant.name} < #{constant.superclass.name} — #{hint_for(constant)}" end end |