module Rails::Generators

Constants

DEFAULT_ALIASES
DEFAULT_OPTIONS
RAILS_DEV_PATH

We need to store the RAILS_DEV_PATH in a constant, otherwise the path can change in Ruby 1.8.7 when we FileUtils.cd.

RESERVED_NAMES

Public Class Methods

api_only!() Show source
# File railties/lib/rails/generators.rb, line 110
def self.api_only!
  hide_namespaces "assets", "helper", "css", "js"

  options[:rails].merge!(
    api: true,
    assets: false,
    helper: false,
    template_engine: nil
  )

  if ARGV.first == 'mailer'
    options[:rails].merge!(template_engine: :erb)
  end
end

Configure generators for API only applications. It basically hides everything that is usually browser related, such as assets and session migration generators, and completely disable helpers and assets so generators such as scaffold won't create them.

fallbacks() Show source
# File railties/lib/rails/generators.rb, line 102
def self.fallbacks
  @fallbacks ||= {}
end

Hold configured generators fallbacks. If a plugin developer wants a generator group to fallback to another group in case of missing generators, they can add a fallback.

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

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

Rails::Generators.fallbacks[:shoulda] = :test_unit
help(command = 'generate') Show source
# File railties/lib/rails/generators.rb, line 235
def self.help(command = 'generate')
  puts "Usage: 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

Show help message with available generators.

hidden_namespaces() Show source
# File railties/lib/rails/generators.rb, line 196
def self.hidden_namespaces
  @hidden_namespaces ||= begin
    orm      = options[:rails][:orm]
    test     = options[:rails][:test_framework]
    template = options[:rails][:template_engine]
    css      = options[:rails][:stylesheet_engine]

    [
      "rails",
      "resource_route",
      "#{orm}:migration",
      "#{orm}:model",
      "#{test}:controller",
      "#{test}:helper",
      "#{test}:integration",
      "#{test}:mailer",
      "#{test}:model",
      "#{test}:scaffold",
      "#{test}:view",
      "#{test}:job",
      "#{template}:controller",
      "#{template}:scaffold",
      "#{template}:mailer",
      "#{css}:scaffold",
      "#{css}:assets",
      "css:assets",
      "css:scaffold"
    ]
  end
end

Returns an array of generator namespaces that are hidden. Generator namespaces may be hidden for a variety of reasons. Some are aliased such as “rails:migration” and can be invoked with the shorter “migration”, others are private to other generators such as “css:scaffold”.

hide_namespace(*namespaces)
Alias for: hide_namespaces
hide_namespaces(*namespaces) Show source
# File railties/lib/rails/generators.rb, line 228
def hide_namespaces(*namespaces)
  hidden_namespaces.concat(namespaces)
end
Also aliased as: hide_namespace
invoke(namespace, args=ARGV, config={}) Show source
# File railties/lib/rails/generators.rb, line 176
def self.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)
  else
    options     = sorted_groups.flat_map(&:last)
    suggestions = options.sort_by {|suggested| levenshtein_distance(namespace.to_s, suggested) }.first(3)
    msg =  "Could not find generator '#{namespace}'. "
    msg << "Maybe you meant #{ suggestions.map {|s| "'#{s}'"}.to_sentence(last_word_connector: " or ", locale: :en) }\n"
    msg << "Run `rails generate --help` for more options."
    puts msg
  end
end

Receives a namespace, arguments and the behavior to invoke the generator. It's used as the default entry point for generate, destroy and update commands.

no_color!() Show source
# File railties/lib/rails/generators.rb, line 126
def self.no_color!
  Thor::Base.shell = Thor::Shell::Basic
end

Remove the color from output.

print_generators() Show source
public_namespaces() Show source
# File railties/lib/rails/generators.rb, line 251
def self.public_namespaces
  lookup!
  subclasses.map(&:namespace)
end
sorted_groups() Show source
# File railties/lib/rails/generators.rb, line 260
def self.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.sub(/^rails:/, '') }
  rails.delete("app")
  rails.delete("plugin")

  hidden_namespaces.each { |n| groups.delete(n.to_s) }

  [["rails", rails]] + groups.sort.to_a
end
subclasses() Show source
# File railties/lib/rails/generators.rb, line 131
def self.subclasses
  @subclasses ||= []
end

Track all generators subclasses.

Protected Class Methods

levenshtein_distance(str1, str2) Show source
# File railties/lib/rails/generators.rb, line 284
def self.levenshtein_distance str1, str2
  s = str1
  t = str2
  n = s.length
  m = t.length

  return m if (0 == n)
  return n if (0 == m)

  d = (0..m).to_a
  x = nil

  # avoid duplicating an enumerable object in the loop
  str2_codepoint_enumerable = str2.each_codepoint

  str1.each_codepoint.with_index do |char1, i|
    e = i+1

    str2_codepoint_enumerable.with_index do |char2, j|
      cost = (char1 == char2) ? 0 : 1
      x = [
           d[j+1] + 1, # insertion
           e + 1,      # deletion
           d[j] + cost # substitution
          ].min
      d[j] = e
      e = x
    end

    d[m] = x
  end

  x
end

This code is based directly on the Text gem implementation. Copyright © 2006-2013 Paul Battley, Michael Neumann, Tim Fletcher.

Returns a value representing the “cost” of transforming str1 into str2

© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.