aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib/rails/commands
diff options
context:
space:
mode:
Diffstat (limited to 'railties/lib/rails/commands')
-rw-r--r--railties/lib/rails/commands/application.rb17
-rw-r--r--railties/lib/rails/commands/commands_tasks.rb169
-rw-r--r--railties/lib/rails/commands/console.rb113
-rw-r--r--railties/lib/rails/commands/dbconsole.rb177
-rw-r--r--railties/lib/rails/commands/destroy.rb9
-rw-r--r--railties/lib/rails/commands/generate.rb11
-rw-r--r--railties/lib/rails/commands/plugin.rb23
-rw-r--r--railties/lib/rails/commands/runner.rb63
-rw-r--r--railties/lib/rails/commands/server.rb152
-rw-r--r--railties/lib/rails/commands/update.rb9
10 files changed, 743 insertions, 0 deletions
diff --git a/railties/lib/rails/commands/application.rb b/railties/lib/rails/commands/application.rb
new file mode 100644
index 0000000000..c998e6b6a8
--- /dev/null
+++ b/railties/lib/rails/commands/application.rb
@@ -0,0 +1,17 @@
+require 'rails/generators'
+require 'rails/generators/rails/app/app_generator'
+
+module Rails
+ module Generators
+ class AppGenerator # :nodoc:
+ # We want to exit on failure to be kind to other libraries
+ # This is only when accessing via CLI
+ def self.exit_on_failure?
+ true
+ end
+ end
+ end
+end
+
+args = Rails::Generators::ARGVScrubber.new(ARGV).prepare!
+Rails::Generators::AppGenerator.start args
diff --git a/railties/lib/rails/commands/commands_tasks.rb b/railties/lib/rails/commands/commands_tasks.rb
new file mode 100644
index 0000000000..6cfbc70c51
--- /dev/null
+++ b/railties/lib/rails/commands/commands_tasks.rb
@@ -0,0 +1,169 @@
+module Rails
+ # This is a class which takes in a rails command and initiates the appropriate
+ # initiation sequence.
+ #
+ # Warning: This class mutates ARGV because some commands require manipulating
+ # it before they are run.
+ class CommandsTasks # :nodoc:
+ attr_reader :argv
+
+ HELP_MESSAGE = <<-EOT
+Usage: rails COMMAND [ARGS]
+
+The most common rails commands are:
+ generate Generate new code (short-cut alias: "g")
+ console Start the Rails console (short-cut alias: "c")
+ server Start the Rails server (short-cut alias: "s")
+ dbconsole Start a console for the database specified in config/database.yml
+ (short-cut alias: "db")
+ new Create a new Rails application. "rails new my_app" creates a
+ new application called MyApp in "./my_app"
+
+In addition to those, there are:
+ destroy Undo code generated with "generate" (short-cut alias: "d")
+ plugin new Generates skeleton for developing a Rails plugin
+ runner Run a piece of code in the application environment (short-cut alias: "r")
+
+All commands can be run with -h (or --help) for more information.
+EOT
+
+ COMMAND_WHITELIST = %w(plugin generate destroy console server dbconsole runner new version help)
+
+ def initialize(argv)
+ @argv = argv
+ end
+
+ def run_command!(command)
+ command = parse_command(command)
+ if COMMAND_WHITELIST.include?(command)
+ send(command)
+ else
+ write_error_message(command)
+ end
+ end
+
+ def plugin
+ require_command!("plugin")
+ end
+
+ def generate
+ generate_or_destroy(:generate)
+ end
+
+ def destroy
+ generate_or_destroy(:destroy)
+ end
+
+ def console
+ require_command!("console")
+ options = Rails::Console.parse_arguments(argv)
+
+ # RAILS_ENV needs to be set before config/application is required
+ ENV['RAILS_ENV'] = options[:environment] if options[:environment]
+
+ # shift ARGV so IRB doesn't freak
+ shift_argv!
+
+ require_application_and_environment!
+ Rails::Console.start(Rails.application, options)
+ end
+
+ def server
+ set_application_directory!
+ require_command!("server")
+
+ Rails::Server.new.tap do |server|
+ # We need to require application after the server sets environment,
+ # otherwise the --environment option given to the server won't propagate.
+ require APP_PATH
+ Dir.chdir(Rails.application.root)
+ server.start
+ end
+ end
+
+ def dbconsole
+ require_command!("dbconsole")
+ Rails::DBConsole.start
+ end
+
+ def runner
+ require_command!("runner")
+ end
+
+ def new
+ if %w(-h --help).include?(argv.first)
+ require_command!("application")
+ else
+ exit_with_initialization_warning!
+ end
+ end
+
+ def version
+ argv.unshift '--version'
+ require_command!("application")
+ end
+
+ def help
+ write_help_message
+ end
+
+ private
+
+ def exit_with_initialization_warning!
+ puts "Can't initialize a new Rails application within the directory of another, please change to a non-Rails directory first.\n"
+ puts "Type 'rails' for help."
+ exit(1)
+ end
+
+ def shift_argv!
+ argv.shift if argv.first && argv.first[0] != '-'
+ end
+
+ def require_command!(command)
+ require "rails/commands/#{command}"
+ end
+
+ def generate_or_destroy(command)
+ require 'rails/generators'
+ require_application_and_environment!
+ Rails.application.load_generators
+ require "rails/commands/#{command}"
+ end
+
+ # Change to the application's path if there is no config.ru file in current directory.
+ # This allows us to run `rails server` from other directories, but still get
+ # the main config.ru and properly set the tmp directory.
+ def set_application_directory!
+ Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exist?(File.expand_path("config.ru"))
+ end
+
+ def require_application_and_environment!
+ require APP_PATH
+ Rails.application.require_environment!
+ end
+
+ def write_help_message
+ puts HELP_MESSAGE
+ end
+
+ def write_error_message(command)
+ puts "Error: Command '#{command}' not recognized"
+ if %x{rake #{command} --dry-run 2>&1 } && $?.success?
+ puts "Did you mean: `$ rake #{command}` ?\n\n"
+ end
+ write_help_message
+ exit(1)
+ end
+
+ def parse_command(command)
+ case command
+ when '--version', '-v'
+ 'version'
+ when '--help', '-h'
+ 'help'
+ else
+ command
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb
new file mode 100644
index 0000000000..555d8f31e1
--- /dev/null
+++ b/railties/lib/rails/commands/console.rb
@@ -0,0 +1,113 @@
+require 'optparse'
+require 'irb'
+require 'irb/completion'
+
+module Rails
+ class Console
+ class << self
+ def start(*args)
+ new(*args).start
+ end
+
+ def parse_arguments(arguments)
+ options = {}
+
+ OptionParser.new do |opt|
+ opt.banner = "Usage: rails console [environment] [options]"
+ opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |v| options[:sandbox] = v }
+ opt.on("-e", "--environment=name", String,
+ "Specifies the environment to run this console under (test/development/production).",
+ "Default: development") { |v| options[:environment] = v.strip }
+ opt.on("--debugger", 'Enable the debugger.') do |v|
+ if RUBY_VERSION < '2.0.0'
+ options[:debugger] = v
+ else
+ puts "=> Notice: debugger option is ignored since ruby 2.0 and " \
+ "it will be removed in future versions"
+ end
+ end
+ opt.parse!(arguments)
+ end
+
+ if arguments.first && arguments.first[0] != '-'
+ env = arguments.first
+ if available_environments.include? env
+ options[:environment] = env
+ else
+ options[:environment] = %w(production development test).detect {|e| e =~ /^#{env}/} || env
+ end
+ end
+
+ options
+ end
+
+ private
+
+ def available_environments
+ Dir['config/environments/*.rb'].map { |fname| File.basename(fname, '.*') }
+ end
+ end
+
+ attr_reader :options, :app, :console
+
+ def initialize(app, options={})
+ @app = app
+ @options = options
+
+ app.sandbox = sandbox?
+ app.load_console
+
+ @console = app.config.console || IRB
+ end
+
+ def sandbox?
+ options[:sandbox]
+ end
+
+ def environment
+ options[:environment] ||= ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
+ end
+
+ def environment?
+ environment
+ end
+
+ def set_environment!
+ Rails.env = environment
+ end
+
+ if RUBY_VERSION < '2.0.0'
+ def debugger?
+ options[:debugger]
+ end
+
+ def require_debugger
+ require 'debugger'
+ puts "=> Debugger enabled"
+ rescue LoadError
+ puts "You're missing the 'debugger' gem. Add it to your Gemfile, bundle it and try again."
+ exit(1)
+ end
+ end
+
+ def start
+ if RUBY_VERSION < '2.0.0'
+ require_debugger if debugger?
+ end
+
+ set_environment! if environment?
+
+ if sandbox?
+ puts "Loading #{Rails.env} environment in sandbox (Rails #{Rails.version})"
+ puts "Any modifications you make will be rolled back on exit"
+ else
+ puts "Loading #{Rails.env} environment (Rails #{Rails.version})"
+ end
+
+ if defined?(console::ExtendCommandBundle)
+ console::ExtendCommandBundle.send :include, Rails::ConsoleMethods
+ end
+ console.start
+ end
+ end
+end
diff --git a/railties/lib/rails/commands/dbconsole.rb b/railties/lib/rails/commands/dbconsole.rb
new file mode 100644
index 0000000000..1a2613a8d0
--- /dev/null
+++ b/railties/lib/rails/commands/dbconsole.rb
@@ -0,0 +1,177 @@
+require 'erb'
+require 'yaml'
+require 'optparse'
+require 'rbconfig'
+
+module Rails
+ class DBConsole
+ attr_reader :arguments
+
+ def self.start
+ new.start
+ end
+
+ def initialize(arguments = ARGV)
+ @arguments = arguments
+ end
+
+ def start
+ options = parse_arguments(arguments)
+ ENV['RAILS_ENV'] = options[:environment] || environment
+
+ case config["adapter"]
+ when /^(jdbc)?mysql/
+ args = {
+ 'host' => '--host',
+ 'port' => '--port',
+ 'socket' => '--socket',
+ 'username' => '--user',
+ 'encoding' => '--default-character-set',
+ 'sslca' => '--ssl-ca',
+ 'sslcert' => '--ssl-cert',
+ 'sslcapath' => '--ssl-capath',
+ 'sslcipher' => '--ssh-cipher',
+ 'sslkey' => '--ssl-key'
+ }.map { |opt, arg| "#{arg}=#{config[opt]}" if config[opt] }.compact
+
+ if config['password'] && options['include_password']
+ args << "--password=#{config['password']}"
+ elsif config['password'] && !config['password'].to_s.empty?
+ args << "-p"
+ end
+
+ args << config['database']
+
+ find_cmd_and_exec(['mysql', 'mysql5'], *args)
+
+ when "postgresql", "postgres", "postgis"
+ ENV['PGUSER'] = config["username"] if config["username"]
+ ENV['PGHOST'] = config["host"] if config["host"]
+ ENV['PGPORT'] = config["port"].to_s if config["port"]
+ ENV['PGPASSWORD'] = config["password"].to_s if config["password"] && options['include_password']
+ find_cmd_and_exec('psql', config["database"])
+
+ when "sqlite"
+ find_cmd_and_exec('sqlite', config["database"])
+
+ when "sqlite3"
+ args = []
+
+ args << "-#{options['mode']}" if options['mode']
+ args << "-header" if options['header']
+ args << File.expand_path(config['database'], Rails.respond_to?(:root) ? Rails.root : nil)
+
+ find_cmd_and_exec('sqlite3', *args)
+
+ when "oracle", "oracle_enhanced"
+ logon = ""
+
+ if config['username']
+ logon = config['username']
+ logon << "/#{config['password']}" if config['password'] && options['include_password']
+ logon << "@#{config['database']}" if config['database']
+ end
+
+ find_cmd_and_exec('sqlplus', logon)
+
+ else
+ abort "Unknown command-line client for #{config['database']}. Submit a Rails patch to add support!"
+ end
+ end
+
+ def config
+ @config ||= begin
+ if configurations[environment].blank?
+ raise ActiveRecord::AdapterNotSpecified, "'#{environment}' database is not configured. Available configuration: #{configurations.inspect}"
+ else
+ configurations[environment]
+ end
+ end
+ end
+
+ def environment
+ if Rails.respond_to?(:env)
+ Rails.env
+ else
+ ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
+ end
+ end
+
+ protected
+
+ def configurations
+ require APP_PATH
+ ActiveRecord::Base.configurations = Rails.application.config.database_configuration
+ ActiveRecord::Base.configurations
+ end
+
+ def parse_arguments(arguments)
+ options = {}
+
+ OptionParser.new do |opt|
+ opt.banner = "Usage: rails dbconsole [environment] [options]"
+ opt.on("-p", "--include-password", "Automatically provide the password from database.yml") do |v|
+ options['include_password'] = true
+ end
+
+ opt.on("--mode [MODE]", ['html', 'list', 'line', 'column'],
+ "Automatically put the sqlite3 database in the specified mode (html, list, line, column).") do |mode|
+ options['mode'] = mode
+ end
+
+ opt.on("--header") do |h|
+ options['header'] = h
+ end
+
+ opt.on("-h", "--help", "Show this help message.") do
+ puts opt
+ exit
+ end
+
+ opt.on("-e", "--environment=name", String,
+ "Specifies the environment to run this console under (test/development/production).",
+ "Default: development"
+ ) { |v| options[:environment] = v.strip }
+
+ opt.parse!(arguments)
+ abort opt.to_s unless (0..1).include?(arguments.size)
+ end
+
+ if arguments.first && arguments.first[0] != '-'
+ env = arguments.first
+ if available_environments.include? env
+ options[:environment] = env
+ else
+ options[:environment] = %w(production development test).detect {|e| e =~ /^#{env}/} || env
+ end
+ end
+
+ options
+ end
+
+ def available_environments
+ Dir['config/environments/*.rb'].map { |fname| File.basename(fname, '.*') }
+ end
+
+ def find_cmd_and_exec(commands, *args)
+ commands = Array(commands)
+
+ dirs_on_path = ENV['PATH'].to_s.split(File::PATH_SEPARATOR)
+ commands += commands.map{|cmd| "#{cmd}.exe"} if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
+
+ full_path_command = nil
+ found = commands.detect do |cmd|
+ dirs_on_path.detect do |path|
+ full_path_command = File.join(path, cmd)
+ File.executable? full_path_command
+ end
+ end
+
+ if found
+ exec full_path_command, *args
+ else
+ abort("Couldn't find database client: #{commands.join(', ')}. Check your $PATH and try again.")
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/commands/destroy.rb b/railties/lib/rails/commands/destroy.rb
new file mode 100644
index 0000000000..5479da86a0
--- /dev/null
+++ b/railties/lib/rails/commands/destroy.rb
@@ -0,0 +1,9 @@
+require 'rails/generators'
+
+if [nil, "-h", "--help"].include?(ARGV.first)
+ Rails::Generators.help 'destroy'
+ exit
+end
+
+name = ARGV.shift
+Rails::Generators.invoke name, ARGV, behavior: :revoke, destination_root: Rails.root
diff --git a/railties/lib/rails/commands/generate.rb b/railties/lib/rails/commands/generate.rb
new file mode 100644
index 0000000000..351c59c645
--- /dev/null
+++ b/railties/lib/rails/commands/generate.rb
@@ -0,0 +1,11 @@
+require 'rails/generators'
+
+if [nil, "-h", "--help"].include?(ARGV.first)
+ Rails::Generators.help 'generate'
+ exit
+end
+
+name = ARGV.shift
+
+root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
+Rails::Generators.invoke name, ARGV, behavior: :invoke, destination_root: root
diff --git a/railties/lib/rails/commands/plugin.rb b/railties/lib/rails/commands/plugin.rb
new file mode 100644
index 0000000000..95bbdd4cdf
--- /dev/null
+++ b/railties/lib/rails/commands/plugin.rb
@@ -0,0 +1,23 @@
+if ARGV.first != "new"
+ ARGV[0] = "--help"
+else
+ ARGV.shift
+ unless ARGV.delete("--no-rc")
+ customrc = ARGV.index{ |x| x.include?("--rc=") }
+ railsrc = if customrc
+ File.expand_path(ARGV.delete_at(customrc).gsub(/--rc=/, ""))
+ else
+ File.join(File.expand_path("~"), '.railsrc')
+ end
+ if File.exist?(railsrc)
+ extra_args_string = File.read(railsrc)
+ extra_args = extra_args_string.split(/\n+/).flat_map {|l| l.split}
+ puts "Using #{extra_args.join(" ")} from #{railsrc}"
+ ARGV.insert(1, *extra_args)
+ end
+ end
+end
+
+require 'rails/generators'
+require 'rails/generators/rails/plugin/plugin_generator'
+Rails::Generators::PluginGenerator.start
diff --git a/railties/lib/rails/commands/runner.rb b/railties/lib/rails/commands/runner.rb
new file mode 100644
index 0000000000..3a71f8d3f8
--- /dev/null
+++ b/railties/lib/rails/commands/runner.rb
@@ -0,0 +1,63 @@
+require 'optparse'
+require 'rbconfig'
+
+options = { environment: (ENV['RAILS_ENV'] || ENV['RACK_ENV'] || "development").dup }
+code_or_file = nil
+
+if ARGV.first.nil?
+ ARGV.push "-h"
+end
+
+ARGV.clone.options do |opts|
+ opts.banner = "Usage: rails runner [options] [<'Some.ruby(code)'> | <filename.rb>]"
+
+ opts.separator ""
+
+ opts.on("-e", "--environment=name", String,
+ "Specifies the environment for the runner to operate under (test/development/production).",
+ "Default: development") { |v| options[:environment] = v }
+
+ opts.separator ""
+
+ opts.on("-h", "--help",
+ "Show this help message.") { $stdout.puts opts; exit }
+
+ opts.separator ""
+ opts.separator "Examples: "
+
+ opts.separator " rails runner 'puts Rails.env'"
+ opts.separator " This runs the code `puts Rails.env` after loading the app"
+ opts.separator ""
+ opts.separator " rails runner path/to/filename.rb"
+ opts.separator " This runs the Ruby file located at `path/to/filename.rb` after loading the app"
+
+ if RbConfig::CONFIG['host_os'] !~ /mswin|mingw/
+ opts.separator ""
+ opts.separator "You can also use runner as a shebang line for your executables:"
+ opts.separator " -------------------------------------------------------------"
+ opts.separator " #!/usr/bin/env #{File.expand_path($0)} runner"
+ opts.separator ""
+ opts.separator " Product.all.each { |p| p.price *= 2 ; p.save! }"
+ opts.separator " -------------------------------------------------------------"
+ end
+
+ opts.order! { |o| code_or_file ||= o } rescue retry
+end
+
+ARGV.delete(code_or_file)
+
+ENV["RAILS_ENV"] = options[:environment]
+
+require APP_PATH
+Rails.application.require_environment!
+Rails.application.load_runner
+
+if code_or_file.nil?
+ $stderr.puts "Run '#{$0} -h' for help."
+ exit 1
+elsif File.exist?(code_or_file)
+ $0 = code_or_file
+ Kernel.load code_or_file
+else
+ eval(code_or_file, binding, __FILE__, __LINE__)
+end
diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb
new file mode 100644
index 0000000000..c3b7bb6f84
--- /dev/null
+++ b/railties/lib/rails/commands/server.rb
@@ -0,0 +1,152 @@
+require 'fileutils'
+require 'optparse'
+require 'action_dispatch'
+require 'rails'
+
+module Rails
+ class Server < ::Rack::Server
+ class Options
+ def parse!(args)
+ args, options = args.dup, {}
+
+ option_parser(options).parse! args
+
+ options[:log_stdout] = options[:daemonize].blank? && (options[:environment] || Rails.env) == "development"
+ options[:server] = args.shift
+ options
+ end
+
+ private
+
+ def option_parser(options)
+ OptionParser.new do |opts|
+ opts.banner = "Usage: rails server [mongrel, thin, etc] [options]"
+ opts.on("-p", "--port=port", Integer,
+ "Runs Rails on the specified port.", "Default: 3000") { |v| options[:Port] = v }
+ opts.on("-b", "--binding=ip", String,
+ "Binds Rails to the specified ip.", "Default: 0.0.0.0") { |v| options[:Host] = v }
+ opts.on("-c", "--config=file", String,
+ "Use custom rackup configuration file") { |v| options[:config] = v }
+ opts.on("-d", "--daemon", "Make server run as a Daemon.") { options[:daemonize] = true }
+ opts.on("-u", "--debugger", "Enable the debugger") do
+ if RUBY_VERSION < '2.0.0'
+ options[:debugger] = true
+ else
+ puts "=> Notice: debugger option is ignored since ruby 2.0 and " \
+ "it will be removed in future versions"
+ end
+ end
+ opts.on("-e", "--environment=name", String,
+ "Specifies the environment to run this server under (test/development/production).",
+ "Default: development") { |v| options[:environment] = v }
+ opts.on("-P", "--pid=pid", String,
+ "Specifies the PID file.",
+ "Default: tmp/pids/server.pid") { |v| options[:pid] = v }
+
+ opts.separator ""
+
+ opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
+ end
+ end
+ end
+
+ def initialize(*)
+ super
+ set_environment
+ end
+
+ # TODO: this is no longer required but we keep it for the moment to support older config.ru files.
+ def app
+ @app ||= begin
+ app = super
+ app.respond_to?(:to_app) ? app.to_app : app
+ end
+ end
+
+ def opt_parser
+ Options.new
+ end
+
+ def set_environment
+ ENV["RAILS_ENV"] ||= options[:environment]
+ end
+
+ def start
+ print_boot_information
+ trap(:INT) { exit }
+ create_tmp_directories
+ log_to_stdout if options[:log_stdout]
+
+ super
+ ensure
+ # The '-h' option calls exit before @options is set.
+ # If we call 'options' with it unset, we get double help banners.
+ puts 'Exiting' unless @options && options[:daemonize]
+ end
+
+ def middleware
+ middlewares = []
+ if RUBY_VERSION < '2.0.0'
+ middlewares << [Rails::Rack::Debugger] if options[:debugger]
+ end
+ middlewares << [::Rack::ContentLength]
+
+ # FIXME: add Rack::Lock in the case people are using webrick.
+ # This is to remain backwards compatible for those who are
+ # running webrick in production. We should consider removing this
+ # in development.
+ if server.name == 'Rack::Handler::WEBrick'
+ middlewares << [::Rack::Lock]
+ end
+
+ Hash.new(middlewares)
+ end
+
+ def log_path
+ "log/#{options[:environment]}.log"
+ end
+
+ def default_options
+ super.merge({
+ Port: 3000,
+ DoNotReverseLookup: true,
+ environment: (ENV['RAILS_ENV'] || ENV['RACK_ENV'] || "development").dup,
+ daemonize: false,
+ debugger: false,
+ pid: File.expand_path("tmp/pids/server.pid"),
+ config: File.expand_path("config.ru")
+ })
+ end
+
+ private
+
+ def print_boot_information
+ url = "#{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}"
+ puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
+ puts "=> Rails #{Rails.version} application starting in #{Rails.env} on #{url}"
+ puts "=> Run `rails server -h` for more startup options"
+
+ if options[:Host].to_s.match(/0\.0\.0\.0/)
+ puts "=> Notice: server is listening on all interfaces (#{options[:Host]}). Consider using 127.0.0.1 (--binding option)"
+ end
+
+ puts "=> Ctrl-C to shutdown server" unless options[:daemonize]
+ end
+
+ def create_tmp_directories
+ %w(cache pids sessions sockets).each do |dir_to_make|
+ FileUtils.mkdir_p(File.join(Rails.root, 'tmp', dir_to_make))
+ end
+ end
+
+ def log_to_stdout
+ wrapped_app # touch the app so the logger is set up
+
+ console = ActiveSupport::Logger.new($stdout)
+ console.formatter = Rails.logger.formatter
+ console.level = Rails.logger.level
+
+ Rails.logger.extend(ActiveSupport::Logger.broadcast(console))
+ end
+ end
+end
diff --git a/railties/lib/rails/commands/update.rb b/railties/lib/rails/commands/update.rb
new file mode 100644
index 0000000000..59fae5c337
--- /dev/null
+++ b/railties/lib/rails/commands/update.rb
@@ -0,0 +1,9 @@
+require File.expand_path(File.join(File.dirname(__FILE__), '..', 'generators'))
+
+if ARGV.size == 0
+ Rails::Generators.help
+ exit
+end
+
+name = ARGV.shift
+Rails::Generators.invoke name, ARGV, behavior: :skip