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/credentials/USAGE2
-rw-r--r--railties/lib/rails/commands/credentials/credentials_command.rb6
-rw-r--r--railties/lib/rails/commands/dbconsole/dbconsole_command.rb2
-rw-r--r--railties/lib/rails/commands/encrypted/encrypted_command.rb7
-rw-r--r--railties/lib/rails/commands/notes/notes_command.rb39
-rw-r--r--railties/lib/rails/commands/routes/routes_command.rb37
-rw-r--r--railties/lib/rails/commands/secrets/USAGE6
-rw-r--r--railties/lib/rails/commands/secrets/secrets_command.rb6
-rw-r--r--railties/lib/rails/commands/server/server_command.rb143
9 files changed, 199 insertions, 49 deletions
diff --git a/railties/lib/rails/commands/credentials/USAGE b/railties/lib/rails/commands/credentials/USAGE
index 85877c71b7..ea429f58d8 100644
--- a/railties/lib/rails/commands/credentials/USAGE
+++ b/railties/lib/rails/commands/credentials/USAGE
@@ -14,7 +14,7 @@ that just contains the secret_key_base used by MessageVerifiers/MessageEncryptor
signing and encrypting cookies.
For applications created prior to Rails 5.2, we'll automatically generate a new
-credentials file in `config/credentials.yml.enc` the first time you run `bin/rails credentials:edit`.
+credentials file in `config/credentials.yml.enc` the first time you run `rails credentials:edit`.
If you didn't have a master key saved in `config/master.key`, that'll be created too.
Don't lose this master key! Put it in a password manager your team can access.
diff --git a/railties/lib/rails/commands/credentials/credentials_command.rb b/railties/lib/rails/commands/credentials/credentials_command.rb
index 385d3976da..65c5218fc8 100644
--- a/railties/lib/rails/commands/credentials/credentials_command.rb
+++ b/railties/lib/rails/commands/credentials/credentials_command.rb
@@ -20,7 +20,7 @@ module Rails
require_application_and_environment!
ensure_editor_available(command: "bin/rails credentials:edit") || (return)
- ensure_master_key_has_been_added
+ ensure_master_key_has_been_added if Rails.application.credentials.key.nil?
ensure_credentials_have_been_added
catch_editing_exceptions do
@@ -69,9 +69,9 @@ module Rails
def missing_credentials_message
if Rails.application.credentials.key.nil?
- "Missing master key to decrypt credentials. See bin/rails credentials:help"
+ "Missing master key to decrypt credentials. See `rails credentials:help`"
else
- "No credentials have been added yet. Use bin/rails credentials:edit to change that."
+ "No credentials have been added yet. Use `rails credentials:edit` to change that."
end
end
end
diff --git a/railties/lib/rails/commands/dbconsole/dbconsole_command.rb b/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
index 8df548b5de..806b7de6d6 100644
--- a/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
+++ b/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
@@ -97,7 +97,7 @@ module Rails
elsif configurations[environment].blank? && configurations[connection].blank?
raise ActiveRecord::AdapterNotSpecified, "'#{environment}' database is not configured. Available configuration: #{configurations.inspect}"
else
- configurations[environment].presence || configurations[connection]
+ configurations[connection] || configurations[environment].presence
end
end
end
diff --git a/railties/lib/rails/commands/encrypted/encrypted_command.rb b/railties/lib/rails/commands/encrypted/encrypted_command.rb
index 912c453f09..8d5947652a 100644
--- a/railties/lib/rails/commands/encrypted/encrypted_command.rb
+++ b/railties/lib/rails/commands/encrypted/encrypted_command.rb
@@ -21,9 +21,10 @@ module Rails
def edit(file_path)
require_application_and_environment!
+ encrypted = Rails.application.encrypted(file_path, key_path: options[:key])
ensure_editor_available(command: "bin/rails encrypted:edit") || (return)
- ensure_encryption_key_has_been_added(options[:key])
+ ensure_encryption_key_has_been_added(options[:key]) if encrypted.key.nil?
ensure_encrypted_file_has_been_added(file_path, options[:key])
catch_editing_exceptions do
@@ -75,9 +76,9 @@ module Rails
def missing_encrypted_message(key:, key_path:, file_path:)
if key.nil?
- "Missing '#{key_path}' to decrypt data. See bin/rails encrypted:help"
+ "Missing '#{key_path}' to decrypt data. See `rails encrypted:help`"
else
- "File '#{file_path}' does not exist. Use bin/rails encrypted:edit #{file_path} to change that."
+ "File '#{file_path}' does not exist. Use `rails encrypted:edit #{file_path}` to change that."
end
end
end
diff --git a/railties/lib/rails/commands/notes/notes_command.rb b/railties/lib/rails/commands/notes/notes_command.rb
new file mode 100644
index 0000000000..64b339b3cd
--- /dev/null
+++ b/railties/lib/rails/commands/notes/notes_command.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require "rails/source_annotation_extractor"
+
+module Rails
+ module Command
+ class NotesCommand < Base # :nodoc:
+ class_option :annotations, aliases: "-a", desc: "Filter by specific annotations, e.g. Foobar TODO", type: :array, default: %w(OPTIMIZE FIXME TODO)
+
+ def perform(*)
+ require_application_and_environment!
+
+ deprecation_warning
+ display_annotations
+ end
+
+ private
+ def display_annotations
+ annotations = options[:annotations]
+ tag = (annotations.length > 1)
+
+ Rails::SourceAnnotationExtractor.enumerate annotations.join("|"), tag: tag, dirs: directories
+ end
+
+ def directories
+ Rails::SourceAnnotationExtractor::Annotation.directories + source_annotation_directories
+ end
+
+ def deprecation_warning
+ return if source_annotation_directories.empty?
+ ActiveSupport::Deprecation.warn("`SOURCE_ANNOTATION_DIRECTORIES` is deprecated and will be removed in Rails 6.1. You can add default directories by using config.annotations.register_directories instead.")
+ end
+
+ def source_annotation_directories
+ ENV["SOURCE_ANNOTATION_DIRECTORIES"].to_s.split(",")
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/commands/routes/routes_command.rb b/railties/lib/rails/commands/routes/routes_command.rb
new file mode 100644
index 0000000000..b592a5212f
--- /dev/null
+++ b/railties/lib/rails/commands/routes/routes_command.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require "rails/command"
+
+module Rails
+ module Command
+ class RoutesCommand < Base # :nodoc:
+ class_option :controller, aliases: "-c", desc: "Filter by a specific controller, e.g. PostsController or Admin::PostsController."
+ class_option :grep, aliases: "-g", desc: "Grep routes by a specific pattern."
+ class_option :expanded, type: :boolean, aliases: "-E", desc: "Print routes expanded vertically with parts explained."
+
+ def perform(*)
+ require_application_and_environment!
+ require "action_dispatch/routing/inspector"
+
+ say inspector.format(formatter, routes_filter)
+ end
+
+ private
+ def inspector
+ ActionDispatch::Routing::RoutesInspector.new(Rails.application.routes.routes)
+ end
+
+ def formatter
+ if options.key?("expanded")
+ ActionDispatch::Routing::ConsoleFormatter::Expanded.new
+ else
+ ActionDispatch::Routing::ConsoleFormatter::Sheet.new
+ end
+ end
+
+ def routes_filter
+ options.symbolize_keys.slice(:controller, :grep)
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/commands/secrets/USAGE b/railties/lib/rails/commands/secrets/USAGE
index 96e322fe91..e205cdc001 100644
--- a/railties/lib/rails/commands/secrets/USAGE
+++ b/railties/lib/rails/commands/secrets/USAGE
@@ -7,7 +7,7 @@ with the code.
=== Setup
-Run `bin/rails secrets:setup` to opt in and generate the `config/secrets.yml.key`
+Run `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
@@ -45,12 +45,12 @@ the key. Add this:
config.read_encrypted_secrets = true
-to the environment you'd like to read encrypted secrets. `bin/rails secrets:setup`
+to the environment you'd like to read encrypted secrets. `rails secrets:setup`
inserts this into the production environment by default.
=== Editing Secrets
-After `bin/rails secrets:setup`, run `bin/rails secrets:edit`.
+After `rails secrets:setup`, run `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.
diff --git a/railties/lib/rails/commands/secrets/secrets_command.rb b/railties/lib/rails/commands/secrets/secrets_command.rb
index a36ccf314c..2eebc0f35f 100644
--- a/railties/lib/rails/commands/secrets/secrets_command.rb
+++ b/railties/lib/rails/commands/secrets/secrets_command.rb
@@ -22,7 +22,7 @@ module Rails
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 %(EDITOR="mate --wait" 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."
@@ -42,7 +42,7 @@ module Rails
rescue Rails::Secrets::MissingKeyError => error
say error.message
rescue Errno::ENOENT => error
- if error.message =~ /secrets\.yml\.enc/
+ if /secrets\.yml\.enc/.match?(error.message)
deprecate_in_favor_of_credentials_and_exit
else
raise
@@ -56,7 +56,7 @@ module Rails
private
def deprecate_in_favor_of_credentials_and_exit
say "Encrypted secrets is deprecated in favor of credentials. Run:"
- say "bin/rails credentials:help"
+ say "rails credentials:help"
exit 1
end
diff --git a/railties/lib/rails/commands/server/server_command.rb b/railties/lib/rails/commands/server/server_command.rb
index 703ec59087..9d517f3239 100644
--- a/railties/lib/rails/commands/server/server_command.rb
+++ b/railties/lib/rails/commands/server/server_command.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
require "fileutils"
-require "optparse"
require "action_dispatch"
require "rails"
require "active_support/deprecation"
@@ -27,7 +26,7 @@ module Rails
app = super
if app.is_a?(Class)
ActiveSupport::Deprecation.warn(<<-MSG.squish)
- Use `Rails::Application` subclass to start the server is deprecated and will be removed in Rails 6.0.
+ Using `Rails::Application` subclass to start the server is deprecated and will be removed in Rails 6.0.
Please change `run #{app}` to `run Rails.application` in config.ru.
MSG
end
@@ -43,18 +42,22 @@ module Rails
ENV["RAILS_ENV"] ||= options[:environment]
end
- def start
- print_boot_information
+ def start(after_stop_callback = nil)
trap(:INT) { exit }
create_tmp_directories
setup_dev_caching
log_to_stdout if options[:log_stdout]
- super
+ 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]
+ after_stop_callback.call if after_stop_callback
+ end
+
+ def serveable? # :nodoc:
+ server
+ true
+ rescue LoadError, NameError
+ false
end
def middleware
@@ -65,6 +68,10 @@ module Rails
super.merge(@default_options)
end
+ def served_url
+ "#{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}" unless use_puma?
+ end
+
private
def setup_dev_caching
if options[:environment] == "development"
@@ -72,13 +79,6 @@ module Rails
end
end
- def print_boot_information
- url = "on #{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}" unless use_puma?
- puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
- puts "=> Rails #{Rails.version} application starting in #{Rails.env} #{url}"
- puts "=> Run `rails server -h` for more startup options"
- end
-
def create_tmp_directories
%w(cache pids sockets).each do |dir_to_make|
FileUtils.mkdir_p(File.join(Rails.root, "tmp", dir_to_make))
@@ -97,10 +97,6 @@ module Rails
end
end
- def restart_command
- "bin/rails server #{ARGV.join(' ')}"
- end
-
def use_puma?
server.to_s == "Rack::Handler::Puma"
end
@@ -108,9 +104,15 @@ module Rails
module Command
class ServerCommand < Base # :nodoc:
+ # Hard-coding a bunch of handlers here as we don't have a public way of
+ # querying them from the Rack::Handler registry.
+ RACK_SERVERS = %w(cgi fastcgi webrick lsws scgi thin puma unicorn)
+
DEFAULT_PORT = 3000
DEFAULT_PID_PATH = "tmp/pids/server.pid".freeze
+ argument :using, optional: true
+
class_option :port, aliases: "-p", type: :numeric,
desc: "Runs Rails on the specified port - defaults to 3000.", banner: :port
class_option :binding, aliases: "-b", type: :string,
@@ -122,29 +124,41 @@ module Rails
desc: "Runs server as a Daemon."
class_option :environment, aliases: "-e", type: :string,
desc: "Specifies the environment to run this server under (development/test/production).", banner: :name
+ class_option :using, aliases: "-u", type: :string,
+ desc: "Specifies the Rack server used to run the application (thin/puma/webrick).", banner: :name
class_option :pid, aliases: "-P", type: :string, default: DEFAULT_PID_PATH,
desc: "Specifies the PID file."
- class_option "dev-caching", aliases: "-C", type: :boolean, default: nil,
+ class_option :dev_caching, aliases: "-C", type: :boolean, default: nil,
desc: "Specifies whether to perform caching in development."
- class_option "restart", type: :boolean, default: nil, hide: true
- class_option "early_hints", type: :boolean, default: nil, desc: "Enables HTTP/2 early hints."
+ class_option :restart, type: :boolean, default: nil, hide: true
+ class_option :early_hints, type: :boolean, default: nil, desc: "Enables HTTP/2 early hints."
+ class_option :log_to_stdout, type: :boolean, default: nil, optional: true,
+ desc: "Whether to log to stdout. Enabled by default in development when not daemonized."
- def initialize(args = [], local_options = {}, config = {})
- @original_options = local_options
+ def initialize(args, local_options, *)
super
- @server = self.args.shift
- @log_stdout = options[:daemon].blank? && (options[:environment] || Rails.env) == "development"
+
+ @original_options = local_options - %w( --restart )
+ deprecate_positional_rack_server_and_rewrite_to_option(@original_options)
end
def perform
set_application_directory!
prepare_restart
+
Rails::Server.new(server_options).tap do |server|
# Require application after server sets environment to propagate
# the --environment option.
require APP_PATH
Dir.chdir(Rails.application.root)
- server.start
+
+ if server.serveable?
+ print_boot_information(server.server, server.served_url)
+ after_stop_callback = -> { say "Exiting" unless options[:daemon] }
+ server.start(after_stop_callback)
+ else
+ say rack_server_suggestion(using)
+ end
end
end
@@ -152,8 +166,8 @@ module Rails
def server_options
{
user_supplied_options: user_supplied_options,
- server: @server,
- log_stdout: @log_stdout,
+ server: using,
+ log_stdout: log_to_stdout?,
Port: port,
Host: host,
DoNotReverseLookup: true,
@@ -161,7 +175,7 @@ module Rails
environment: environment,
daemonize: options[:daemon],
pid: pid,
- caching: options["dev-caching"],
+ caching: options[:dev_caching],
restart_cmd: restart_command,
early_hints: early_hints
}
@@ -194,7 +208,7 @@ module Rails
name = :Port
when :binding
name = :Host
- when :"dev-caching"
+ when :dev_caching
name = :caching
when :daemonize
name = :daemon
@@ -202,7 +216,7 @@ module Rails
user_supplied_options << name
end
end
- user_supplied_options << :Host if ENV["HOST"]
+ user_supplied_options << :Host if ENV["HOST"] || ENV["BINDING"]
user_supplied_options << :Port if ENV["PORT"]
user_supplied_options.uniq
end
@@ -217,7 +231,17 @@ module Rails
options[:binding]
else
default_host = environment == "development" ? "localhost" : "0.0.0.0"
- ENV.fetch("HOST", default_host)
+
+ if ENV["HOST"] && !ENV["BINDING"]
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
+ Using the `HOST` environment to specify the IP is deprecated and will be removed in Rails 6.1.
+ Please use `BINDING` environment instead.
+ MSG
+
+ return ENV["HOST"]
+ end
+
+ ENV.fetch("BINDING", default_host)
end
end
@@ -226,24 +250,73 @@ module Rails
end
def restart_command
- "bin/rails server #{@server} #{@original_options.join(" ")} --restart"
+ "bin/rails server #{@original_options.join(" ")} --restart"
end
def early_hints
options[:early_hints]
end
+ def log_to_stdout?
+ options.fetch(:log_to_stdout) do
+ options[:daemon].blank? && environment == "development"
+ end
+ end
+
def pid
File.expand_path(options[:pid])
end
def self.banner(*)
- "rails server [puma, thin etc] [options]"
+ "rails server [thin/puma/webrick] [options]"
end
def prepare_restart
FileUtils.rm_f(options[:pid]) if options[:restart]
end
+
+ def deprecate_positional_rack_server_and_rewrite_to_option(original_options)
+ if using
+ ActiveSupport::Deprecation.warn(<<~MSG)
+ Passing the Rack server name as a regular argument is deprecated
+ and will be removed in the next Rails version. Please, use the -u
+ option instead.
+ MSG
+
+ original_options.concat [ "-u", using ]
+ else
+ # Use positional internally to get around Thor's immutable options.
+ # TODO: Replace `using` occurrences with `options[:using]` after deprecation removal.
+ @using = options[:using]
+ end
+ end
+
+ def rack_server_suggestion(server)
+ if server.in?(RACK_SERVERS)
+ <<~MSG
+ Could not load server "#{server}". Maybe you need to the add it to the Gemfile?
+
+ gem "#{server}"
+
+ Run `rails server --help` for more options.
+ MSG
+ else
+ suggestion = Rails::Command::Spellchecker.suggest(server, from: RACK_SERVERS)
+
+ <<~MSG
+ Could not find server "#{server}". Maybe you meant #{suggestion.inspect}?
+ Run `rails server --help` for more options.
+ MSG
+ end
+ end
+
+ def print_boot_information(server, url)
+ say <<~MSG
+ => Booting #{ActiveSupport::Inflector.demodulize(server)}
+ => Rails #{Rails.version} application starting in #{Rails.env} #{url}
+ => Run `rails server --help` for more startup options
+ MSG
+ end
end
end
end