module Rails::Generators

def add_generated_file(file) # :nodoc:

:nodoc:
def add_generated_file(file) # :nodoc:
  (@@generated_files ||= []) << file
  file
end

def after_generate_callbacks # :nodoc:

:nodoc:
def after_generate_callbacks # :nodoc:
  @after_generate_callbacks ||= []
end

def aliases # :nodoc:

:nodoc:
def aliases # :nodoc:
  @aliases ||= DEFAULT_ALIASES.dup
end

def api_only!

so generators such as scaffold won't create them.
migration generators, and completely disable helpers and assets
everything that is usually browser related, such as assets and session
Configure generators for API only applications. It basically hides
def api_only!
  hide_namespaces "assets", "helper", "css", "js"
  options[:rails].merge!(
    api: true,
    assets: false,
    helper: false,
    template_engine: nil
  )
  options[:mailer] ||= {}
  options[:mailer][:template_engine] ||= :erb
end

def command_type # :doc:

:doc:
def command_type # :doc:
  @command_type ||= "generator"
end

def configure!(config) # :nodoc:

:nodoc:
def configure!(config) # :nodoc:
  api_only! if config.api_only
  no_color! unless config.colorize_logging
  aliases.deep_merge! config.aliases
  options.deep_merge! config.options
  fallbacks.merge! config.fallbacks
  templates_path.concat config.templates
  templates_path.uniq!
  hide_namespaces(*config.hidden_namespaces)
  after_generate_callbacks.replace config.after_generate_callbacks
end

def fallbacks

Rails::Generators.fallbacks[:shoulda] = :test_unit

some of them are not available by adding a fallback:
Shoulda then can tell generators to search for +test_unit+ generators when

+test_unit+ ones.
of +test_unit+. However, most part of shoulda generators are similar to
For example, shoulda is considered a +test_framework+ and is an extension

they can add a fallback.
generator group to fall back to another group in case of missing generators,
Hold configured generators fallbacks. If a plugin developer wants a
def fallbacks
  @fallbacks ||= {}
end

def file_lookup_paths # :doc:

:doc:
def file_lookup_paths # :doc:
  @file_lookup_paths ||= [ "{#{lookup_paths.join(',')}}", "**", "*_generator.rb" ]
end

def find_by_namespace(name, base = nil, context = nil) # :nodoc:

:nodoc:
Rails looks for is the first and last parts of the namespace.
Notice that "rails:generators:webrat" could be loaded as well, what

"rails:webrat", "webrat:integration", "webrat"

Will search for the following generators:

find_by_namespace :webrat, :rails, :integration

looks in load paths and loads the generator just before it's going to be used.
Generators names must end with "_generator.rb". This is required because Rails

Rails finds namespaces similar to Thor, it only adds one rule:
def find_by_namespace(name, base = nil, context = nil) # :nodoc:
  lookups = []
  lookups << "#{base}:#{name}"    if base
  lookups << "#{name}:#{context}" if context
  unless base || context
    unless name.to_s.include?(?:)
      lookups << "#{name}:#{name}"
      lookups << "rails:#{name}"
    end
    lookups << "#{name}"
  end
  lookup(lookups)
  namespaces = subclasses.index_by(&:namespace)
  lookups.each do |namespace|
    klass = namespaces[namespace]
    return klass if klass
  end
  invoke_fallbacks_for(name, base) || invoke_fallbacks_for(context, name)
end

def help(command = "generate")

Show help message with available generators.
def help(command = "generate")
  puts "Usage:"
  puts "  bin/rails #{command} GENERATOR [args] [options]"
  puts
  puts "General options:"
  puts "  -h, [--help]     # Print generator's options and usage"
  puts "  -p, [--pretend]  # Run but do not make any changes"
  puts "  -f, [--force]    # Overwrite files that already exist"
  puts "  -s, [--skip]     # Skip files that already exist"
  puts "  -q, [--quiet]    # Suppress status output"
  puts
  puts "Please choose a generator below."
  puts
  print_generators
end

def hidden_namespaces

invoked with the shorter "migration".
Some are aliased such as "rails:migration" and can be
Generator namespaces may be hidden for a variety of reasons.
Returns an array of generator namespaces that are hidden.
def hidden_namespaces
  @hidden_namespaces ||= begin
    orm      = options[:rails][:orm]
    test     = options[:rails][:test_framework]
    template = options[:rails][:template_engine]
    [
      "rails",
      "resource_route",
      "#{orm}:migration",
      "#{orm}:model",
      "#{test}:controller",
      "#{test}:helper",
      "#{test}:integration",
      "#{test}:system",
      "#{test}:mailer",
      "#{test}:model",
      "#{test}:scaffold",
      "#{test}:view",
      "#{test}:job",
      "#{template}:controller",
      "#{template}:scaffold",
      "#{template}:mailer",
      "action_text:install",
      "action_mailbox:install",
      "devcontainer"
    ]
  end
end

def hide_namespaces(*namespaces)

def hide_namespaces(*namespaces)
  hidden_namespaces.concat(namespaces)
end

def invoke(namespace, args = ARGV, config = {})

commands.
It's used as the default entry point for generate, destroy, and update
Receives a namespace, arguments, and the behavior to invoke the generator.
def invoke(namespace, args = ARGV, config = {})
  names = namespace.to_s.split(":")
  if klass = find_by_namespace(names.pop, names.any? && names.join(":"))
    args << "--help" if args.empty? && klass.arguments.any?(&:required?)
    klass.start(args, config)
    run_after_generate_callback if config[:behavior] == :invoke
  else
    options = sorted_groups.flat_map(&:last)
    error = Command::CorrectableNameError.new("Could not find generator '#{namespace}'.", namespace, options)
    puts <<~MSG
      #{error.detailed_message}
      Run `bin/rails generate --help` for more options.
    MSG
    exit 1
  end
end

def invoke_fallbacks_for(name, base)

Try fallbacks for the given base.
def invoke_fallbacks_for(name, base)
  return nil unless base && fallbacks[base.to_sym]
  invoked_fallbacks = []
  Array(fallbacks[base.to_sym]).each do |fallback|
    next if invoked_fallbacks.include?(fallback)
    invoked_fallbacks << fallback
    klass = find_by_namespace(name, fallback)
    return klass if klass
  end
  nil
end

def lookup_paths # :doc:

:doc:
def lookup_paths # :doc:
  @lookup_paths ||= %w( rails/generators generators )
end

def options # :nodoc:

:nodoc:
def options # :nodoc:
  @options ||= DEFAULT_OPTIONS.dup
end

def print_generators

def print_generators
  sorted_groups.each { |b, n| print_list(b, n) }
end

def print_list(base, namespaces) # :doc:

:doc:
def print_list(base, namespaces) # :doc:
  namespaces = namespaces.reject { |n| hidden_namespaces.include?(n) }
  super
end

def public_namespaces

def public_namespaces
  lookup!
  subclasses.map(&:namespace)
end

def run_after_generate_callback

def run_after_generate_callback
  if defined?(@@generated_files) && !@@generated_files.empty?
    after_generate_callbacks.each do |callback|
      callback.call(@@generated_files)
    end
    @@generated_files = []
  end
end

def sorted_groups

def sorted_groups
  namespaces = public_namespaces
  namespaces.sort!
  groups = Hash.new { |h, k| h[k] = [] }
  namespaces.each do |namespace|
    base = namespace.split(":").first
    groups[base] << namespace
  end
  rails = groups.delete("rails")
  rails.map! { |n| n.delete_prefix("rails:") }
  rails.delete("app")
  rails.delete("plugin")
  rails.delete("encrypted_file")
  rails.delete("encryption_key_file")
  rails.delete("master_key")
  rails.delete("credentials")
  rails.delete("db:system:change")
  hidden_namespaces.each { |n| groups.delete(n.to_s) }
  [[ "rails", rails ]] + groups.sort.to_a
end

def templates_path # :nodoc:

:nodoc:
def templates_path # :nodoc:
  @templates_path ||= []
end