Refactor EnvironmentArgument to be automatic

This commit refactors `Rails::Command::EnvironmentArgument` to
automatically set an appropriate value for `options[:environment]`, even
when the `--environment` option is omitted.  Additionally,
`EnvironmentArgument` will automatically set `ENV["RAILS_ENV"]` when
`require_application!` (or `require_application_and_environment!`) is
called.
This commit is contained in:
Jonathan Hefner 2023-01-19 11:22:41 -06:00
parent bcc1eb727b
commit dad25b69fb
10 changed files with 42 additions and 71 deletions

View File

@ -9,31 +9,47 @@ module Rails
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do included do
no_commands do class_option :environment, aliases: "-e", type: :string,
class_attribute :environment_desc, default: "Specifies the environment to run this #{self.command_name} under (test/development/production)." desc: "The environment to run `#{self.command_name}` in (e.g. test / development / production)."
end
def initialize(...)
super
@environment_specified = options[:environment].present?
if !@environment_specified
self.options = options.merge(environment: Rails::Command.environment)
elsif !available_environments.include?(options[:environment])
self.options = options.merge(environment: expand_environment_name(options[:environment]))
end end
class_option :environment, aliases: "-e", type: :string, desc: environment_desc
end end
private private
def extract_environment_option_from_argument(default_environment: Rails::Command.environment) def require_application!
if options[:environment] ENV["RAILS_ENV"] = environment
self.options = options.merge(environment: acceptable_environment(options[:environment])) super
else
self.options = options.merge(environment: default_environment)
end
end end
def acceptable_environment(env = nil) def environment
if available_environments.include? env @environment ||= options[:environment]
env end
else
%w( production development test ).detect { |e| /^#{env}/.match?(e) } || env def environment=(environment)
end @environment = environment
end
def environment_specified?
@environment_specified
end end
def available_environments def available_environments
Dir["config/environments/*.rb"].map { |fname| File.basename(fname, ".*") } @available_environments ||=
Dir["config/environments/*.rb"].map { |filename| File.basename(filename, ".*") }
end
def expand_environment_name(name)
%w[production development test].find { |full_name| full_name.start_with?(name) } || name
end end
end end
end end

View File

@ -97,11 +97,6 @@ module Rails
end end
def perform 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! require_application_and_environment!
Rails::Console.start(Rails.application, options) Rails::Console.start(Rails.application, options)
end end

View File

@ -24,19 +24,16 @@ module Rails
desc "edit", "Opens the decrypted credentials in `$EDITOR` for editing" desc "edit", "Opens the decrypted credentials in `$EDITOR` for editing"
def edit def edit
environment_specified = options[:environment].present?
extract_environment_option_from_argument
ENV["RAILS_ENV"] = options[:environment]
require_application! require_application!
load_generators load_generators
if environment_specified if environment_specified?
@content_path = "config/credentials/#{options[:environment]}.yml.enc" unless config.key?(:content_path) @content_path = "config/credentials/#{environment}.yml.enc" unless config.key?(:content_path)
@key_path = "config/credentials/#{options[:environment]}.key" unless config.key?(:key_path) @key_path = "config/credentials/#{environment}.key" unless config.key?(:key_path)
end end
ensure_encryption_key_has_been_added ensure_encryption_key_has_been_added
ensure_credentials_have_been_added(environment_specified) ensure_credentials_have_been_added
ensure_diffing_driver_is_configured ensure_diffing_driver_is_configured
change_credentials_in_system_editor change_credentials_in_system_editor
@ -44,8 +41,6 @@ module Rails
desc "show", "Shows the decrypted credentials" desc "show", "Shows the decrypted credentials"
def show def show
extract_environment_option_from_argument
ENV["RAILS_ENV"] = options[:environment]
require_application! require_application!
say credentials.read.presence || missing_credentials_message say credentials.read.presence || missing_credentials_message
@ -60,8 +55,7 @@ module Rails
desc "diff", "Enrolls/disenrolls in decrypted diffs of credentials using git" desc "diff", "Enrolls/disenrolls in decrypted diffs of credentials using git"
def diff(content_path = nil) def diff(content_path = nil)
if @content_path = content_path if @content_path = content_path
extract_environment_option_from_argument(default_environment: extract_environment_from_path(content_path)) self.environment = extract_environment_from_path(content_path)
ENV["RAILS_ENV"] = options[:environment]
require_application! require_application!
say credentials.read.presence || credentials.content_path.read say credentials.read.presence || credentials.content_path.read
@ -100,12 +94,12 @@ module Rails
encryption_key_file_generator.ignore_key_file(key_path) encryption_key_file_generator.ignore_key_file(key_path)
end end
def ensure_credentials_have_been_added(environment_specified) def ensure_credentials_have_been_added
require "rails/generators/rails/credentials/credentials_generator" require "rails/generators/rails/credentials/credentials_generator"
Rails::Generators::CredentialsGenerator.new( Rails::Generators::CredentialsGenerator.new(
[content_path, key_path], [content_path, key_path],
skip_secret_key_base: environment_specified && %w[development test].include?(options[:environment]), skip_secret_key_base: environment_specified? && %w[development test].include?(environment),
quiet: true quiet: true
).invoke_all ).invoke_all
end end

View File

@ -89,11 +89,6 @@ module Rails
desc: "Specifies the database to use." desc: "Specifies the database to use."
def perform 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! require_application_and_environment!
Rails::DBConsole.start(options) Rails::DBConsole.start(options)
end end

View File

@ -9,9 +9,6 @@ module Rails
desc "initializers", "Print out all defined initializers in the order they are invoked by Rails." desc "initializers", "Print out all defined initializers in the order they are invoked by Rails."
def perform def perform
extract_environment_option_from_argument
ENV["RAILS_ENV"] = options[:environment]
require_application_and_environment! require_application_and_environment!
Rails.application.initializers.tsort_each do |initializer| Rails.application.initializers.tsort_each do |initializer|

View File

@ -7,8 +7,6 @@ module Rails
class RunnerCommand < Base # :nodoc: class RunnerCommand < Base # :nodoc:
include EnvironmentArgument include EnvironmentArgument
self.environment_desc = "The environment for the runner to operate under (test/development/production)"
no_commands do no_commands do
def help def help
super super
@ -22,15 +20,11 @@ module Rails
desc "runner", "Runs Ruby code in the context of your application" desc "runner", "Runs Ruby code in the context of your application"
def perform(code_or_file = nil, *command_argv) def perform(code_or_file = nil, *command_argv)
extract_environment_option_from_argument
unless code_or_file unless code_or_file
help help
exit 1 exit 1
end end
ENV["RAILS_ENV"] = options[:environment]
require_application_and_environment! require_application_and_environment!
Rails.application.load_runner Rails.application.load_runner

View File

@ -129,7 +129,6 @@ module Rails
end end
def perform def perform
extract_environment_option_from_argument
set_application_directory! set_application_directory!
prepare_restart prepare_restart

View File

@ -184,8 +184,6 @@ class Rails::ConsoleTest < ActiveSupport::TestCase
end end
def parse_arguments(args) def parse_arguments(args)
command = Rails::Command::ConsoleCommand.new([], args) Rails::Command::ConsoleCommand.new([], args).options
command.send(:extract_environment_option_from_argument)
command.options
end end
end end

View File

@ -246,21 +246,6 @@ class Rails::DBConsoleTest < ActiveSupport::TestCase
end end
def parse_arguments(args) def parse_arguments(args)
Rails::Command::DbconsoleCommand.class_eval do Rails::Command::DbconsoleCommand.new([], args).options
alias_method :old_perform, :perform
define_method(:perform) do
extract_environment_option_from_argument
options
end
end
Rails::Command.invoke(:dbconsole, args)
ensure
Rails::Command::DbconsoleCommand.class_eval do
undef_method :perform
alias_method :perform, :old_perform
undef_method :old_perform
end
end end
end end

View File

@ -303,8 +303,6 @@ class Rails::Command::ServerCommandTest < ActiveSupport::TestCase
end end
def parse_arguments(args = []) def parse_arguments(args = [])
command = Rails::Command::ServerCommand.new([], args) Rails::Command::ServerCommand.new([], args).server_options
command.send(:extract_environment_option_from_argument)
command.server_options
end end
end end