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/application_command.rb4
-rw-r--r--railties/lib/rails/commands/console/console_command.rb19
-rw-r--r--railties/lib/rails/commands/dbconsole/dbconsole_command.rb27
-rw-r--r--railties/lib/rails/commands/destroy/destroy_command.rb15
-rw-r--r--railties/lib/rails/commands/generate/generate_command.rb11
-rw-r--r--railties/lib/rails/commands/help/USAGE33
-rw-r--r--railties/lib/rails/commands/new/new_command.rb6
-rw-r--r--railties/lib/rails/commands/plugin/plugin_command.rb4
-rw-r--r--railties/lib/rails/commands/runner/runner_command.rb13
-rw-r--r--railties/lib/rails/commands/secrets/USAGE60
-rw-r--r--railties/lib/rails/commands/secrets/secrets_command.rb64
-rw-r--r--railties/lib/rails/commands/server/server_command.rb87
-rw-r--r--railties/lib/rails/commands/test/test_command.rb38
13 files changed, 302 insertions, 79 deletions
diff --git a/railties/lib/rails/commands/application/application_command.rb b/railties/lib/rails/commands/application/application_command.rb
index 7675d3b3d1..e92daf9be6 100644
--- a/railties/lib/rails/commands/application/application_command.rb
+++ b/railties/lib/rails/commands/application/application_command.rb
@@ -1,5 +1,5 @@
-require "rails/generators"
-require "rails/generators/rails/app/app_generator"
+require_relative "../../generators"
+require_relative "../../generators/rails/app/app_generator"
module Rails
module Generators
diff --git a/railties/lib/rails/commands/console/console_command.rb b/railties/lib/rails/commands/console/console_command.rb
index 62e3aa19df..6f9a1f022b 100644
--- a/railties/lib/rails/commands/console/console_command.rb
+++ b/railties/lib/rails/commands/console/console_command.rb
@@ -1,7 +1,7 @@
require "irb"
require "irb/completion"
-require "rails/command/environment_argument"
+require_relative "../../command/environment_argument"
module Rails
class Console
@@ -70,8 +70,19 @@ module Rails
class_option :sandbox, aliases: "-s", type: :boolean, default: false,
desc: "Rollback database modifications on exit."
- class_option :environment, aliases: "-e", type: :string,
- desc: "Specifies the environment to run this console under (test/development/production)."
+ def initialize(args = [], local_options = {}, config = {})
+ console_options = []
+
+ # For the same behavior as OptionParser, leave only options after "--" in ARGV.
+ termination = local_options.find_index("--")
+ if termination
+ console_options = local_options[termination + 1..-1]
+ local_options = local_options[0...termination]
+ end
+
+ ARGV.replace(console_options)
+ super(args, local_options, config)
+ end
def perform
extract_environment_option_from_argument
@@ -79,8 +90,6 @@ module Rails
# RAILS_ENV needs to be set before config/application is required.
ENV["RAILS_ENV"] = options[:environment]
- ARGV.clear # Clear ARGV so IRB doesn't freak.
-
require_application_and_environment!
Rails::Console.start(Rails.application, options)
end
diff --git a/railties/lib/rails/commands/dbconsole/dbconsole_command.rb b/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
index 588fb06b15..71b3455473 100644
--- a/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
+++ b/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
@@ -1,4 +1,4 @@
-require "rails/command/environment_argument"
+require_relative "../../command/environment_argument"
module Rails
class DBConsole
@@ -11,7 +11,7 @@ module Rails
end
def start
- ENV["RAILS_ENV"] = @options[:environment] || environment
+ ENV["RAILS_ENV"] ||= @options[:environment] || environment
case config["adapter"]
when /^(jdbc)?mysql/
@@ -87,10 +87,15 @@ module Rails
def config
@config ||= begin
- if configurations[environment].blank?
+ # We need to check whether the user passed the connection the
+ # first time around to show a consistent error message to people
+ # relying on 2-level database configuration.
+ if @options["connection"] && configurations[connection].blank?
+ raise ActiveRecord::AdapterNotSpecified, "'#{connection}' connection is not configured. Available configuration: #{configurations.inspect}"
+ elsif configurations[environment].blank? && configurations[connection].blank?
raise ActiveRecord::AdapterNotSpecified, "'#{environment}' database is not configured. Available configuration: #{configurations.inspect}"
else
- configurations[environment]
+ configurations[environment].presence || configurations[connection]
end
end
end
@@ -99,6 +104,10 @@ module Rails
Rails.respond_to?(:env) ? Rails.env : Rails::Command.environment
end
+ def connection
+ @options.fetch(:connection, "primary")
+ end
+
private
def configurations # :doc:
require APP_PATH
@@ -140,14 +149,18 @@ module Rails
class_option :mode, enum: %w( html list line column ), type: :string,
desc: "Automatically put the sqlite3 database in the specified mode (html, list, line, column)."
- class_option :header, type: :string
+ class_option :header, type: :boolean
- class_option :environment, aliases: "-e", type: :string,
- desc: "Specifies the environment to run this console under (test/development/production)."
+ class_option :connection, aliases: "-c", type: :string,
+ desc: "Specifies the connection to use."
def perform
extract_environment_option_from_argument
+ # RAILS_ENV needs to be set before config/application is required.
+ ENV["RAILS_ENV"] = options[:environment]
+
+ require_application_and_environment!
Rails::DBConsole.start(options)
end
end
diff --git a/railties/lib/rails/commands/destroy/destroy_command.rb b/railties/lib/rails/commands/destroy/destroy_command.rb
index 5b552b2070..8a6fe67f77 100644
--- a/railties/lib/rails/commands/destroy/destroy_command.rb
+++ b/railties/lib/rails/commands/destroy/destroy_command.rb
@@ -1,10 +1,15 @@
-require "rails/generators"
+require_relative "../../generators"
module Rails
module Command
class DestroyCommand < Base # :nodoc:
- def help
- Rails::Generators.help self.class.command_name
+ no_commands do
+ def help
+ require_application_and_environment!
+ load_generators
+
+ Rails::Generators.help self.class.command_name
+ end
end
def perform(*)
@@ -12,9 +17,9 @@ module Rails
return help unless generator
require_application_and_environment!
- Rails.application.load_generators
+ load_generators
- Rails::Generators.invoke generator, args, behavior: :revoke, destination_root: Rails.root
+ Rails::Generators.invoke generator, args, behavior: :revoke, destination_root: Rails::Command.root
end
end
end
diff --git a/railties/lib/rails/commands/generate/generate_command.rb b/railties/lib/rails/commands/generate/generate_command.rb
index aa8dab71b0..c2089dbcb7 100644
--- a/railties/lib/rails/commands/generate/generate_command.rb
+++ b/railties/lib/rails/commands/generate/generate_command.rb
@@ -1,10 +1,15 @@
-require "rails/generators"
+require_relative "../../generators"
module Rails
module Command
class GenerateCommand < Base # :nodoc:
- def help
- Rails::Generators.help self.class.command_name
+ no_commands do
+ def help
+ require_application_and_environment!
+ load_generators
+
+ Rails::Generators.help self.class.command_name
+ end
end
def perform(*)
diff --git a/railties/lib/rails/commands/help/USAGE b/railties/lib/rails/commands/help/USAGE
index 348f41861f..8eb98319d2 100644
--- a/railties/lib/rails/commands/help/USAGE
+++ b/railties/lib/rails/commands/help/USAGE
@@ -1,27 +1,16 @@
-Usage: bin/rails COMMAND [args] [options]
-<% if engine? %>
-The common Rails commands available for engines are:
- generate Generate new code (short-cut alias: "g")
- destroy Undo code generated with "generate" (short-cut alias: "d")
- test Run tests (short-cut alias: "t")
-
-All commands can be run with -h for more information.
-
-If you want to run any commands that need to be run in context
-of the application, like `bin/rails server` or `bin/rails console`,
-you should do it from the application's directory (typically test/dummy).
-<% else %>
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")
- test Run tests (short-cut alias: "t")
- 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"
+ 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")
+ test Run tests except system tests (short-cut alias: "t")
+ test:system Run system tests
+ dbconsole Start a console for the database specified in config/database.yml
+ (short-cut alias: "db")
+<% unless engine? %>
+ new Create a new Rails application. "rails new my_app" creates a
+ new application called MyApp in "./my_app"
+<% end %>
All commands can be run with -h (or --help) for more information.
-<% end %>
In addition to those commands, there are:
diff --git a/railties/lib/rails/commands/new/new_command.rb b/railties/lib/rails/commands/new/new_command.rb
index 74d1fa5021..207dd5d995 100644
--- a/railties/lib/rails/commands/new/new_command.rb
+++ b/railties/lib/rails/commands/new/new_command.rb
@@ -1,8 +1,10 @@
module Rails
module Command
class NewCommand < Base # :nodoc:
- def help
- Rails::Command.invoke :application, [ "--help" ]
+ no_commands do
+ def help
+ Rails::Command.invoke :application, [ "--help" ]
+ end
end
def perform(*)
diff --git a/railties/lib/rails/commands/plugin/plugin_command.rb b/railties/lib/rails/commands/plugin/plugin_command.rb
index b40ab006af..e915a24e5b 100644
--- a/railties/lib/rails/commands/plugin/plugin_command.rb
+++ b/railties/lib/rails/commands/plugin/plugin_command.rb
@@ -34,8 +34,8 @@ module Rails
private
def run_plugin_generator(plugin_args)
- require "rails/generators"
- require "rails/generators/rails/plugin/plugin_generator"
+ require_relative "../../generators"
+ require_relative "../../generators/rails/plugin/plugin_generator"
Rails::Generators::PluginGenerator.start plugin_args
end
end
diff --git a/railties/lib/rails/commands/runner/runner_command.rb b/railties/lib/rails/commands/runner/runner_command.rb
index 4989a7837d..6864a9726b 100644
--- a/railties/lib/rails/commands/runner/runner_command.rb
+++ b/railties/lib/rails/commands/runner/runner_command.rb
@@ -5,16 +5,18 @@ module Rails
default: Rails::Command.environment.dup,
desc: "The environment for the runner to operate under (test/development/production)"
- def help
- super
- puts self.class.desc
+ no_commands do
+ def help
+ super
+ puts self.class.desc
+ end
end
def self.banner(*)
"#{super} [<'Some.ruby(code)'> | <filename.rb>]"
end
- def perform(code_or_file = nil, *file_argv)
+ def perform(code_or_file = nil, *command_argv)
unless code_or_file
help
exit 1
@@ -25,9 +27,10 @@ module Rails
require_application_and_environment!
Rails.application.load_runner
+ ARGV.replace(command_argv)
+
if File.exist?(code_or_file)
$0 = code_or_file
- ARGV.replace(file_argv)
Kernel.load code_or_file
else
begin
diff --git a/railties/lib/rails/commands/secrets/USAGE b/railties/lib/rails/commands/secrets/USAGE
new file mode 100644
index 0000000000..96e322fe91
--- /dev/null
+++ b/railties/lib/rails/commands/secrets/USAGE
@@ -0,0 +1,60 @@
+=== Storing Encrypted Secrets in Source Control
+
+The Rails `secrets` commands helps encrypting secrets to slim a production
+environment's `ENV` hash. It's also useful for atomic deploys: no need to
+coordinate key changes to get everything working as the keys are shipped
+with the code.
+
+=== Setup
+
+Run `bin/rails secrets:setup` to opt in and generate the `config/secrets.yml.key`
+and `config/secrets.yml.enc` files.
+
+The latter contains all the keys to be encrypted while the former holds the
+encryption key.
+
+Don't lose the key! Put it in a password manager your team can access.
+Should you lose it no one, including you, will be able to access any encrypted
+secrets.
+Don't commit the key! Add `config/secrets.yml.key` to your source control's
+ignore file. If you use Git, Rails handles this for you.
+
+Rails also looks for the key in `ENV["RAILS_MASTER_KEY"]` if that's easier to
+manage.
+
+You could prepend that to your server's start command like this:
+
+ RAILS_MASTER_KEY="im-the-master-now-hahaha" server.start
+
+
+The `config/secrets.yml.enc` has much the same format as `config/secrets.yml`:
+
+ production:
+ secret_key_base: so-secret-very-hidden-wow
+ payment_processing_gateway_key: much-safe-very-gaedwey-wow
+
+But that's where the similarities between `secrets.yml` and `secrets.yml.enc`
+end, e.g. no keys from `secrets.yml` will be moved to `secrets.yml.enc` and
+be encrypted.
+
+A `shared:` top level key is also supported such that any keys there is merged
+into the other environments.
+
+Additionally, Rails won't read encrypted secrets out of the box even if you have
+the key. Add this:
+
+ config.read_encrypted_secrets = true
+
+to the environment you'd like to read encrypted secrets. `bin/rails secrets:setup`
+inserts this into the production environment by default.
+
+=== Editing Secrets
+
+After `bin/rails secrets:setup`, run `bin/rails secrets:edit`.
+
+That command opens a temporary file in `$EDITOR` with the decrypted contents of
+`config/secrets.yml.enc` to edit the encrypted secrets.
+
+When the temporary file is next saved the contents are encrypted and written to
+`config/secrets.yml.enc` while the file itself is destroyed to prevent secrets
+from leaking.
diff --git a/railties/lib/rails/commands/secrets/secrets_command.rb b/railties/lib/rails/commands/secrets/secrets_command.rb
new file mode 100644
index 0000000000..45e02fa730
--- /dev/null
+++ b/railties/lib/rails/commands/secrets/secrets_command.rb
@@ -0,0 +1,64 @@
+require "active_support"
+require_relative "../../secrets"
+
+module Rails
+ module Command
+ class SecretsCommand < Rails::Command::Base # :nodoc:
+ no_commands do
+ def help
+ say "Usage:\n #{self.class.banner}"
+ say ""
+ say self.class.desc
+ end
+ end
+
+ def setup
+ generator.start
+ end
+
+ def edit
+ if ENV["EDITOR"].to_s.empty?
+ say "No $EDITOR to open decrypted secrets in. Assign one like this:"
+ say ""
+ say %(EDITOR="mate --wait" bin/rails secrets:edit)
+ say ""
+ say "For editors that fork and exit immediately, it's important to pass a wait flag,"
+ say "otherwise the secrets will be saved immediately with no chance to edit."
+
+ return
+ end
+
+ require_application_and_environment!
+
+ Rails::Secrets.read_for_editing do |tmp_path|
+ system("#{ENV["EDITOR"]} #{tmp_path}")
+ end
+
+ say "New secrets encrypted and saved."
+ rescue Interrupt
+ say "Aborted changing encrypted secrets: nothing saved."
+ rescue Rails::Secrets::MissingKeyError => error
+ say error.message
+ rescue Errno::ENOENT => error
+ raise unless error.message =~ /secrets\.yml\.enc/
+
+ Rails::Secrets.read_template_for_editing do |tmp_path|
+ system("#{ENV["EDITOR"]} #{tmp_path}")
+ generator.skip_secrets_file { setup }
+ end
+ end
+
+ def show
+ say Rails::Secrets.read
+ end
+
+ private
+ def generator
+ require_relative "../../generators"
+ require_relative "../../generators/rails/encrypted_secrets/encrypted_secrets_generator"
+
+ Rails::Generators::EncryptedSecretsGenerator
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/commands/server/server_command.rb b/railties/lib/rails/commands/server/server_command.rb
index 15c636103b..b607a63176 100644
--- a/railties/lib/rails/commands/server/server_command.rb
+++ b/railties/lib/rails/commands/server/server_command.rb
@@ -2,7 +2,7 @@ require "fileutils"
require "optparse"
require "action_dispatch"
require "rails"
-require "rails/dev_caching"
+require_relative "../../dev_caching"
module Rails
class Server < ::Rack::Server
@@ -95,12 +95,14 @@ module Rails
module Command
class ServerCommand < Base # :nodoc:
- DEFAULT_PID_PATH = File.expand_path("tmp/pids/server.pid").freeze
+ DEFAULT_PORT = 3000
+ DEFAULT_PID_PATH = "tmp/pids/server.pid".freeze
class_option :port, aliases: "-p", type: :numeric,
- desc: "Runs Rails on the specified port.", banner: :port, default: 3000
- class_option :binding, aliases: "-b", type: :string, default: "localhost",
- desc: "Binds Rails to the specified IP.", banner: :IP
+ desc: "Runs Rails on the specified port - defaults to 3000.", banner: :port
+ class_option :binding, aliases: "-b", type: :string,
+ desc: "Binds Rails to the specified IP - defaults to 'localhost' in development and '0.0.0.0' in other environments'.",
+ banner: :IP
class_option :config, aliases: "-c", type: :string, default: "config.ru",
desc: "Uses a custom rackup configuration.", banner: :file
class_option :daemon, aliases: "-d", type: :boolean, default: false,
@@ -133,28 +135,73 @@ module Rails
no_commands do
def server_options
{
- server: @server,
- log_stdout: @log_stdout,
- Port: port,
- Host: host,
- DoNotReverseLookup: true,
- config: options[:config],
- environment: environment,
- daemonize: options[:daemon],
- pid: options[:pid],
- caching: options["dev-caching"],
- restart_cmd: restart_command
+ user_supplied_options: user_supplied_options,
+ server: @server,
+ log_stdout: @log_stdout,
+ Port: port,
+ Host: host,
+ DoNotReverseLookup: true,
+ config: options[:config],
+ environment: environment,
+ daemonize: options[:daemon],
+ pid: pid,
+ caching: options["dev-caching"],
+ restart_cmd: restart_command
}
end
end
private
+ def user_supplied_options
+ @user_supplied_options ||= begin
+ # Convert incoming options array to a hash of flags
+ # ["-p3001", "-C", "--binding", "127.0.0.1"] # => {"-p"=>true, "-C"=>true, "--binding"=>true}
+ user_flag = {}
+ @original_options.each do |command|
+ if command.to_s.start_with?("--")
+ option = command.split("=")[0]
+ user_flag[option] = true
+ elsif command =~ /\A(-.)/
+ user_flag[Regexp.last_match[0]] = true
+ end
+ end
+
+ # Collect all options that the user has explicitly defined so we can
+ # differentiate them from defaults
+ user_supplied_options = []
+ self.class.class_options.select do |key, option|
+ if option.aliases.any? { |name| user_flag[name] } || user_flag["--#{option.name}"]
+ name = option.name.to_sym
+ case name
+ when :port
+ name = :Port
+ when :binding
+ name = :Host
+ when :"dev-caching"
+ name = :caching
+ when :daemonize
+ name = :daemon
+ end
+ user_supplied_options << name
+ end
+ end
+ user_supplied_options << :Host if ENV["HOST"]
+ user_supplied_options << :Port if ENV["PORT"]
+ user_supplied_options.uniq
+ end
+ end
+
def port
- ENV.fetch("PORT", options[:port]).to_i
+ options[:port] || ENV.fetch("PORT", DEFAULT_PORT).to_i
end
def host
- ENV.fetch("HOST", options[:binding])
+ if options[:binding]
+ options[:binding]
+ else
+ default_host = environment == "development" ? "localhost" : "0.0.0.0"
+ ENV.fetch("HOST", default_host)
+ end
end
def environment
@@ -165,6 +212,10 @@ module Rails
"bin/rails server #{@server} #{@original_options.join(" ")}"
end
+ def pid
+ File.expand_path(options[:pid])
+ end
+
def self.banner(*)
"rails server [puma, thin etc] [options]"
end
diff --git a/railties/lib/rails/commands/test/test_command.rb b/railties/lib/rails/commands/test/test_command.rb
index 7bf8f61137..5852f51a62 100644
--- a/railties/lib/rails/commands/test/test_command.rb
+++ b/railties/lib/rails/commands/test/test_command.rb
@@ -1,19 +1,41 @@
-require "rails/command"
-require "rails/test_unit/minitest_plugin"
+require_relative "../../command"
+require_relative "../../test_unit/runner"
module Rails
module Command
class TestCommand < Base # :nodoc:
- def help
- perform # Hand over help printing to minitest.
+ no_commands do
+ def help
+ require "optparse"
+ require "minitest/rails_plugin"
+
+ opts = OptionParser.new
+ opts.banner = "Usage: #{Rails::TestUnitReporter.executable} [options] [files or directories]"
+ opts.separator ""
+ opts.separator "You can run a single test by appending a line number to a filename:"
+ opts.separator ""
+ opts.separator " #{Rails::TestUnitReporter.executable} test/models/user_test.rb:27"
+ opts.separator ""
+ opts.separator "You can run multiple files and directories at the same time:"
+ opts.separator ""
+ opts.separator " #{Rails::TestUnitReporter.executable} test/controllers test/integration/login_test.rb"
+ opts.separator ""
+ opts.separator "By default test failures and errors are reported inline during a run."
+ opts.separator ""
+
+ opts.separator "Rails options:"
+ Rails::TestUnit::Runner.options(opts)
+ Minitest.plugin_rails_options(opts, {})
+
+ say opts
+ end
end
def perform(*)
- $LOAD_PATH << Rails::Command.root.join("test")
-
- Minitest.run_via[:rails] = true
+ $LOAD_PATH << Rails::Command.root.join("test").to_s
- require "active_support/testing/autorun"
+ Rails::TestUnit::Runner.parse_options(ARGV)
+ Rails::TestUnit::Runner.run(ARGV)
end
end
end