Module: LcpRuby::Generators::Prerequisites

Included in:
ApiTokensGenerator, EntityGenerator, ImportGenerator
Defined in:
lib/lcp_ruby/generators/prerequisites.rb

Overview

Mixin for ‘lcp_ruby:<feature>` generators that enforces declarative prerequisites declared via `requires_features :foo, :bar`.

The concern installs ‘check_lcp_prerequisites!` as the FIRST Thor task on the host generator (via `define_method` in the `included` hook — see `define_method` ordering verification in the design doc). It runs before any file write; on a missing prereq it raises `Thor::Error` with a copy-pasteable hint.

Usage:

class ImportGenerator < Rails::Generators::Base
  include FormatSupport
  include LcpRuby::Generators::Prerequisites
  requires_features :background_jobs
  # … rest of generator
end

For option-driven prereqs (entity generator’s ‘–auditing`, `–custom-fields`), override the instance hook:

def lcp_dynamic_required_features
  out = []
  out << "auditing"      if options[:auditing]
  out << "custom_fields" if options[:custom_fields]
  out
end

Include order: ‘Prerequisites` must come before any explicit `def` in the host generator. `FormatSupport` (which adds only a `class_option`, not a Thor task) may come either before or after.

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/lcp_ruby/generators/prerequisites.rb', line 39

def self.included(base)
  base.extend ClassMethods

  # Defining `check_lcp_prerequisites!` via `base.define_method`
  # (rather than as a plain module instance method) is intentional:
  # only methods on the generator class itself appear in
  # `public_instance_methods(false)`, which is what Thor uses to
  # enumerate tasks. Module-body `def`s are inherited but invisible
  # to Thor's task discovery — exactly what helper methods like
  # `lcp_format_missing_prereqs` (below) need.
  base.send :define_method, :check_lcp_prerequisites! do
    static  = self.class.lcp_required_features
    dynamic = respond_to?(:lcp_dynamic_required_features) ? Array(lcp_dynamic_required_features) : []
    required = (static + dynamic).map(&:to_s).uniq
    return if required.empty?

    missing = required.reject { |f| FeatureRegistry.installed?(f, destination_root) }
    return if missing.empty?

    raise Thor::Error, lcp_format_missing_prereqs(missing)
  end
end

Instance Method Details

#lcp_format_missing_prereqs(missing) ⇒ Object

Helper — kept as a module-body ‘def` so Thor does NOT register it as a task. Visible as an instance method on the host generator via normal `include` resolution.



65
66
67
68
69
70
71
72
73
74
75
# File 'lib/lcp_ruby/generators/prerequisites.rb', line 65

def lcp_format_missing_prereqs(missing)
  lines = [ "Missing prerequisite feature(s): #{missing.join(', ')}", "", "This generator requires:" ]
  missing.each do |feat|
    provides = FeatureRegistry::FEATURES.dig(feat, :provides_models) || []
    suffix   = provides.any? ? " (provides: #{provides.join(', ')})" : ""
    lines << "  - lcp_ruby:#{feat}#{suffix}"
  end
  lines << ""
  lines << "Run them in order, or run `bundle exec rake lcp_ruby:doctor` to see the full dependency graph."
  lines.join("\n")
end