Module: DevDoc::Test::Lints::DomainClassBase

Defined in:
lib/dev_doc/test/lints/domain_class_base.rb

Overview

Domain-class base tripwire: every class under app/models/ must be one of the project's three kinds — persisted (ApplicationRecord), form-backed (ApplicationModel), or plain domain logic (PlainModel).

Rationale

The three-way rule (backend/03_model.md item 9) makes the author classify each domain class at creation time; the base's docstring then states the contract that kind carries. Static analysis cannot enforce totality — RuboCop sees one file at a time, so it cannot resolve whether class Foo < SomeFamilyBase ultimately reaches an allowed base. This lint checks real ancestry with the app loaded, so intermediate bases resolve and the rule is enforced literally. Rails/ApplicationRecord and DevDoc/Rails/ApplicationModelBase remain useful beside it for editor-time feedback on the two common direct mistakes.

NOTE: Limitations:

  • Only classes whose files live under app/models/ are checked; a domain class parked elsewhere is invisible (placement itself is the orchestration taxonomy's reviewer-owned residual).
  • Modules are skipped by design (namespaces, function-bag modules, concerns) — the rule classifies classes.

Usage

Include this module in a Minitest test class (Rails test env) in a project whose three bases exist. Override the constants on the test class to rename bases or exempt a sanctioned file:

class DomainClassBaseTest < ActiveSupport::TestCase
include DevDoc::Test::Lints::DomainClassBase
# DOMAIN_BASE_CLASS_NAMES = %w[ApplicationRecord ApplicationModel PlainModel].freeze
# ALLOWED_DOMAIN_CLASS_PATHS = %w[app/models/legacy/].freeze
end

Constant Summary collapse

DOMAIN_BASE_CLASS_NAMES =

Defaults. Per-project override: redefine the constants on the test class that includes this module.

DomainClassBaseChecker::DEFAULT_BASE_CLASS_NAMES
ALLOWED_DOMAIN_CLASS_PATHS =
[].freeze

Instance Method Summary collapse

Instance Method Details

#test_every_model_class_descends_from_a_domain_baseObject



114
115
116
117
118
119
120
121
122
# File 'lib/dev_doc/test/lints/domain_class_base.rb', line 114

def test_every_model_class_descends_from_a_domain_base
  offenders = DomainClassBaseChecker.new(
    Rails.root,
    base_class_names: self.class::DOMAIN_BASE_CLASS_NAMES,
    allowed_paths: self.class::ALLOWED_DOMAIN_CLASS_PATHS
  ).offenders

  assert offenders.empty?, domain_class_base_message(offenders)
end