railties 5.2.4 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +284 -130
  3. data/MIT-LICENSE +1 -1
  4. data/RDOC_MAIN.rdoc +38 -31
  5. data/README.rdoc +2 -2
  6. data/lib/minitest/rails_plugin.rb +7 -11
  7. data/lib/rails.rb +5 -0
  8. data/lib/rails/all.rb +4 -0
  9. data/lib/rails/api/generator.rb +2 -1
  10. data/lib/rails/api/task.rb +16 -0
  11. data/lib/rails/app_loader.rb +2 -2
  12. data/lib/rails/app_updater.rb +3 -1
  13. data/lib/rails/application.rb +71 -29
  14. data/lib/rails/application/bootstrap.rb +2 -10
  15. data/lib/rails/application/configuration.rb +113 -13
  16. data/lib/rails/application/default_middleware_stack.rb +3 -0
  17. data/lib/rails/application/dummy_erb_compiler.rb +18 -0
  18. data/lib/rails/application/finisher.rb +54 -0
  19. data/lib/rails/autoloaders.rb +48 -0
  20. data/lib/rails/backtrace_cleaner.rb +5 -17
  21. data/lib/rails/code_statistics.rb +3 -3
  22. data/lib/rails/command.rb +11 -10
  23. data/lib/rails/command/base.rb +12 -8
  24. data/lib/rails/command/behavior.rb +7 -48
  25. data/lib/rails/command/environment_argument.rb +8 -15
  26. data/lib/rails/command/spellchecker.rb +58 -0
  27. data/lib/rails/commands/console/console_command.rb +6 -0
  28. data/lib/rails/commands/credentials/USAGE +19 -1
  29. data/lib/rails/commands/credentials/credentials_command.rb +52 -19
  30. data/lib/rails/commands/db/system/change/change_command.rb +20 -0
  31. data/lib/rails/commands/dbconsole/dbconsole_command.rb +20 -8
  32. data/lib/rails/commands/dev/dev_command.rb +19 -0
  33. data/lib/rails/commands/encrypted/USAGE +1 -1
  34. data/lib/rails/commands/encrypted/encrypted_command.rb +2 -2
  35. data/lib/rails/commands/help/help_command.rb +1 -1
  36. data/lib/rails/commands/initializers/initializers_command.rb +23 -0
  37. data/lib/rails/commands/new/new_command.rb +2 -2
  38. data/lib/rails/commands/notes/notes_command.rb +39 -0
  39. data/lib/rails/commands/plugin/plugin_command.rb +1 -1
  40. data/lib/rails/commands/routes/routes_command.rb +37 -0
  41. data/lib/rails/commands/runner/runner_command.rb +13 -9
  42. data/lib/rails/commands/secrets/USAGE +3 -3
  43. data/lib/rails/commands/secrets/secrets_command.rb +3 -3
  44. data/lib/rails/commands/server/server_command.rb +113 -50
  45. data/lib/rails/configuration.rb +1 -7
  46. data/lib/rails/engine.rb +24 -16
  47. data/lib/rails/engine/configuration.rb +5 -2
  48. data/lib/rails/gem_version.rb +3 -3
  49. data/lib/rails/generators.rb +11 -10
  50. data/lib/rails/generators/actions.rb +52 -39
  51. data/lib/rails/generators/app_base.rb +52 -92
  52. data/lib/rails/generators/app_name.rb +50 -0
  53. data/lib/rails/generators/base.rb +0 -4
  54. data/lib/rails/generators/database.rb +58 -0
  55. data/lib/rails/generators/erb/mailer/mailer_generator.rb +1 -1
  56. data/lib/rails/generators/erb/scaffold/templates/_form.html.erb.tt +6 -3
  57. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +1 -1
  58. data/lib/rails/generators/erb/scaffold/templates/show.html.erb.tt +9 -1
  59. data/lib/rails/generators/generated_attribute.rb +53 -27
  60. data/lib/rails/generators/migration.rb +1 -2
  61. data/lib/rails/generators/model_helpers.rb +8 -1
  62. data/lib/rails/generators/named_base.rb +1 -5
  63. data/lib/rails/generators/rails/app/app_generator.rb +37 -72
  64. data/lib/rails/generators/rails/app/templates/Gemfile.tt +7 -10
  65. data/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt +0 -3
  66. data/lib/rails/generators/rails/app/templates/app/{assets/javascripts/cable.js.tt → javascript/channels/consumer.js} +2 -9
  67. data/lib/rails/generators/rails/app/templates/app/javascript/channels/index.js +5 -0
  68. data/lib/rails/generators/rails/app/templates/app/javascript/packs/application.js.tt +23 -0
  69. data/lib/rails/generators/rails/app/templates/app/jobs/application_job.rb.tt +5 -0
  70. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +4 -4
  71. data/lib/rails/generators/rails/app/templates/bin/setup.tt +7 -7
  72. data/lib/rails/generators/rails/app/templates/config/application.rb.tt +2 -0
  73. data/lib/rails/generators/rails/app/templates/config/cable.yml.tt +1 -1
  74. data/lib/rails/generators/rails/app/templates/config/databases/frontbase.yml.tt +2 -2
  75. data/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml.tt +2 -2
  76. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +2 -2
  77. data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt +3 -3
  78. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +3 -3
  79. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +1 -1
  80. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +4 -4
  81. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +2 -2
  82. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +6 -6
  83. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +1 -1
  84. data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +2 -2
  85. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +5 -2
  86. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +28 -12
  87. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +13 -7
  88. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +1 -1
  89. data/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +7 -0
  90. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt +45 -0
  91. data/lib/rails/generators/rails/app/templates/config/locales/en.yml +1 -1
  92. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +4 -3
  93. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +1 -1
  94. data/lib/rails/generators/rails/app/templates/config/spring.rb.tt +6 -6
  95. data/lib/rails/generators/rails/app/templates/gitignore.tt +2 -7
  96. data/lib/rails/generators/rails/app/templates/package.json.tt +7 -1
  97. data/lib/rails/generators/rails/app/templates/public/robots.txt +1 -1
  98. data/lib/rails/generators/rails/app/templates/ruby-version.tt +1 -1
  99. data/lib/rails/generators/rails/app/templates/test/channels/application_cable/connection_test.rb.tt +11 -0
  100. data/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt +7 -0
  101. data/lib/rails/generators/rails/assets/USAGE +1 -4
  102. data/lib/rails/generators/rails/assets/assets_generator.rb +0 -1
  103. data/lib/rails/generators/rails/controller/controller_generator.rb +11 -1
  104. data/lib/rails/generators/rails/credentials/credentials_generator.rb +7 -8
  105. data/lib/rails/generators/rails/db/system/change/change_generator.rb +65 -0
  106. data/lib/rails/generators/rails/encrypted_file/encrypted_file_generator.rb +4 -5
  107. data/lib/rails/generators/rails/helper/helper_generator.rb +5 -0
  108. data/lib/rails/generators/rails/plugin/plugin_generator.rb +9 -33
  109. data/lib/rails/generators/rails/plugin/templates/app/controllers/%namespaced_name%/application_controller.rb.tt +1 -1
  110. data/lib/rails/generators/rails/plugin/templates/app/helpers/%namespaced_name%/application_helper.rb.tt +1 -1
  111. data/lib/rails/generators/rails/plugin/templates/app/jobs/%namespaced_name%/application_job.rb.tt +1 -1
  112. data/lib/rails/generators/rails/plugin/templates/app/mailers/%namespaced_name%/application_mailer.rb.tt +1 -1
  113. data/lib/rails/generators/rails/plugin/templates/app/models/%namespaced_name%/application_record.rb.tt +1 -1
  114. data/lib/rails/generators/rails/plugin/templates/gitignore.tt +1 -1
  115. data/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb.tt +1 -1
  116. data/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/railtie.rb.tt +1 -1
  117. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +1 -2
  118. data/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb +14 -0
  119. data/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt +1 -1
  120. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt +1 -1
  121. data/lib/rails/generators/resource_helpers.rb +1 -6
  122. data/lib/rails/generators/test_unit/integration/integration_generator.rb +6 -0
  123. data/lib/rails/generators/test_unit/job/job_generator.rb +5 -0
  124. data/lib/rails/generators/test_unit/mailer/mailer_generator.rb +1 -1
  125. data/lib/rails/generators/test_unit/model/templates/fixtures.yml.tt +2 -2
  126. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +8 -3
  127. data/lib/rails/generators/test_unit/system/system_generator.rb +5 -0
  128. data/lib/rails/generators/testing/behaviour.rb +3 -0
  129. data/lib/rails/info.rb +2 -2
  130. data/lib/rails/info_controller.rb +1 -1
  131. data/lib/rails/mailers_controller.rb +7 -4
  132. data/lib/rails/paths.rb +19 -9
  133. data/lib/rails/railtie.rb +1 -1
  134. data/lib/rails/ruby_version_check.rb +3 -3
  135. data/lib/rails/secrets.rb +0 -1
  136. data/lib/rails/source_annotation_extractor.rb +138 -117
  137. data/lib/rails/tasks.rb +1 -0
  138. data/lib/rails/tasks/annotations.rake +9 -9
  139. data/lib/rails/tasks/dev.rake +5 -4
  140. data/lib/rails/tasks/framework.rake +5 -1
  141. data/lib/rails/tasks/initializers.rake +5 -4
  142. data/lib/rails/tasks/log.rake +0 -1
  143. data/lib/rails/tasks/routes.rake +4 -26
  144. data/lib/rails/tasks/statistics.rake +4 -0
  145. data/lib/rails/tasks/yarn.rake +1 -1
  146. data/lib/rails/tasks/zeitwerk.rake +66 -0
  147. data/lib/rails/templates/rails/welcome/index.html.erb +2 -2
  148. data/lib/rails/test_help.rb +11 -9
  149. data/lib/rails/test_unit/reporter.rb +1 -1
  150. data/lib/rails/test_unit/runner.rb +5 -5
  151. data/lib/rails/test_unit/testing.rake +1 -1
  152. metadata +32 -23
  153. data/lib/rails/generators/js/assets/assets_generator.rb +0 -15
  154. data/lib/rails/generators/js/assets/templates/javascript.js +0 -2
  155. data/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt +0 -22
  156. data/lib/rails/generators/rails/app/templates/bin/bundle.tt +0 -2
  157. data/lib/rails/generators/rails/app/templates/bin/update.tt +0 -34
  158. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_5_2.rb.tt +0 -38
  159. data/lib/rails/generators/rails/assets/templates/javascript.js +0 -2
@@ -4,7 +4,6 @@ require "active_support"
4
4
  require "active_support/dependencies/autoload"
5
5
  require "active_support/core_ext/enumerable"
6
6
  require "active_support/core_ext/object/blank"
7
- require "active_support/core_ext/hash/transform_values"
8
7
 
9
8
  require "thor"
10
9
 
@@ -12,6 +11,7 @@ module Rails
12
11
  module Command
13
12
  extend ActiveSupport::Autoload
14
13
 
14
+ autoload :Spellchecker
15
15
  autoload :Behavior
16
16
  autoload :Base
17
17
 
@@ -83,20 +83,21 @@ module Rails
83
83
  end
84
84
 
85
85
  def print_commands # :nodoc:
86
- sorted_groups.each { |b, n| print_list(b, n) }
86
+ commands.each { |command| puts(" #{command}") }
87
87
  end
88
88
 
89
- def sorted_groups # :nodoc:
90
- lookup!
89
+ private
90
+ COMMANDS_IN_USAGE = %w(generate console server test test:system dbconsole new)
91
+ private_constant :COMMANDS_IN_USAGE
91
92
 
92
- groups = (subclasses - hidden_commands).group_by { |c| c.namespace.split(":").first }
93
- groups.transform_values! { |commands| commands.flat_map(&:printing_commands).sort }
93
+ def commands
94
+ lookup!
94
95
 
95
- rails = groups.delete("rails")
96
- [[ "rails", rails ]] + groups.sort.to_a
97
- end
96
+ visible_commands = (subclasses - hidden_commands).flat_map(&:printing_commands)
97
+
98
+ (visible_commands - COMMANDS_IN_USAGE).sort
99
+ end
98
100
 
99
- private
100
101
  def command_type # :doc:
101
102
  @command_type ||= "command"
102
103
  end
@@ -17,10 +17,6 @@ module Rails
17
17
  include Actions
18
18
 
19
19
  class << self
20
- def exit_on_failure? # :nodoc:
21
- false
22
- end
23
-
24
20
  # Returns true when the app is a Rails engine.
25
21
  def engine?
26
22
  defined?(ENGINE_ROOT)
@@ -74,7 +70,7 @@ module Rails
74
70
  end
75
71
 
76
72
  def executable
77
- "bin/rails #{command_name}"
73
+ "rails #{command_name}"
78
74
  end
79
75
 
80
76
  # Use Rails' default banner.
@@ -119,7 +115,7 @@ module Rails
119
115
  # For a Rails::Command::TestCommand placed in <tt>rails/command/test_command.rb</tt>
120
116
  # would return <tt>rails/test</tt>.
121
117
  def default_command_root
122
- path = File.expand_path(File.join("../commands", command_root_namespace), __dir__)
118
+ path = File.expand_path(relative_command_path, __dir__)
123
119
  path if File.exist?(path)
124
120
  end
125
121
 
@@ -139,12 +135,20 @@ module Rails
139
135
  end
140
136
 
141
137
  def command_root_namespace
142
- (namespace.split(":") - %w( rails )).first
138
+ (namespace.split(":") - %w(rails)).join(":")
139
+ end
140
+
141
+ def relative_command_path
142
+ File.join("../commands", *command_root_namespace.split(":"))
143
143
  end
144
144
 
145
145
  def namespaced_commands
146
146
  commands.keys.map do |key|
147
- key == command_root_namespace ? key : "#{command_root_namespace}:#{key}"
147
+ if command_root_namespace.match?(/(\A|\:)#{key}\z/)
148
+ command_root_namespace
149
+ else
150
+ "#{command_root_namespace}:#{key}"
151
+ end
148
152
  end
149
153
  end
150
154
  end
@@ -19,46 +19,6 @@ module Rails
19
19
  end
20
20
 
21
21
  private
22
-
23
- # This code is based directly on the Text gem implementation.
24
- # Copyright (c) 2006-2013 Paul Battley, Michael Neumann, Tim Fletcher.
25
- #
26
- # Returns a value representing the "cost" of transforming str1 into str2.
27
- def levenshtein_distance(str1, str2) # :doc:
28
- s = str1
29
- t = str2
30
- n = s.length
31
- m = t.length
32
-
33
- return m if (0 == n)
34
- return n if (0 == m)
35
-
36
- d = (0..m).to_a
37
- x = nil
38
-
39
- # avoid duplicating an enumerable object in the loop
40
- str2_codepoint_enumerable = str2.each_codepoint
41
-
42
- str1.each_codepoint.with_index do |char1, i|
43
- e = i + 1
44
-
45
- str2_codepoint_enumerable.with_index do |char2, j|
46
- cost = (char1 == char2) ? 0 : 1
47
- x = [
48
- d[j + 1] + 1, # insertion
49
- e + 1, # deletion
50
- d[j] + cost # substitution
51
- ].min
52
- d[j] = e
53
- e = x
54
- end
55
-
56
- d[m] = x
57
- end
58
-
59
- x
60
- end
61
-
62
22
  # Prints a list of generators.
63
23
  def print_list(base, namespaces)
64
24
  return if namespaces.empty?
@@ -96,12 +56,10 @@ module Rails
96
56
  def lookup!
97
57
  $LOAD_PATH.each do |base|
98
58
  Dir[File.join(base, *file_lookup_paths)].each do |path|
99
- begin
100
- path = path.sub("#{base}/", "")
101
- require path
102
- rescue Exception
103
- # No problem
104
- end
59
+ path = path.sub("#{base}/", "")
60
+ require path
61
+ rescue Exception
62
+ # No problem
105
63
  end
106
64
  end
107
65
  end
@@ -113,8 +71,9 @@ module Rails
113
71
  paths = []
114
72
  namespaces.each do |namespace|
115
73
  pieces = namespace.split(":")
116
- paths << pieces.dup.push(pieces.last).join("/")
117
- paths << pieces.join("/")
74
+ path = pieces.join("/")
75
+ paths << "#{path}/#{pieces.last}"
76
+ paths << path
118
77
  end
119
78
  paths.uniq!
120
79
  paths
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support"
4
+ require "active_support/core_ext/class/attribute"
4
5
 
5
6
  module Rails
6
7
  module Command
@@ -8,26 +9,18 @@ module Rails
8
9
  extend ActiveSupport::Concern
9
10
 
10
11
  included do
11
- argument :environment, optional: true, banner: "environment"
12
-
13
- class_option :environment, aliases: "-e", type: :string,
14
- desc: "Specifies the environment to run this console under (test/development/production)."
12
+ no_commands do
13
+ class_attribute :environment_desc, default: "Specifies the environment to run this #{self.command_name} under (test/development/production)."
14
+ end
15
+ class_option :environment, aliases: "-e", type: :string, desc: environment_desc
15
16
  end
16
17
 
17
18
  private
18
- def extract_environment_option_from_argument
19
- if environment
20
- self.options = options.merge(environment: acceptable_environment(environment))
21
-
22
- ActiveSupport::Deprecation.warn "Passing the environment's name as a " \
23
- "regular argument is deprecated and " \
24
- "will be removed in the next Rails " \
25
- "version. Please, use the -e option " \
26
- "instead."
27
- elsif options[:environment]
19
+ def extract_environment_option_from_argument(default_environment: Rails::Command.environment)
20
+ if options[:environment]
28
21
  self.options = options.merge(environment: acceptable_environment(options[:environment]))
29
22
  else
30
- self.options = options.merge(environment: Rails::Command.environment)
23
+ self.options = options.merge(environment: default_environment)
31
24
  end
32
25
  end
33
26
 
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ module Command
5
+ module Spellchecker # :nodoc:
6
+ class << self
7
+ def suggest(word, from:)
8
+ if defined?(DidYouMean::SpellChecker)
9
+ DidYouMean::SpellChecker.new(dictionary: from.map(&:to_s)).correct(word).first
10
+ else
11
+ from.sort_by { |w| levenshtein_distance(word, w) }.first
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ # This code is based directly on the Text gem implementation.
18
+ # Copyright (c) 2006-2013 Paul Battley, Michael Neumann, Tim Fletcher.
19
+ #
20
+ # Returns a value representing the "cost" of transforming str1 into str2.
21
+ def levenshtein_distance(str1, str2) # :doc:
22
+ s = str1
23
+ t = str2
24
+ n = s.length
25
+ m = t.length
26
+
27
+ return m if 0 == n
28
+ return n if 0 == m
29
+
30
+ d = (0..m).to_a
31
+ x = nil
32
+
33
+ # avoid duplicating an enumerable object in the loop
34
+ str2_codepoint_enumerable = str2.each_codepoint
35
+
36
+ str1.each_codepoint.with_index do |char1, i|
37
+ e = i + 1
38
+
39
+ str2_codepoint_enumerable.with_index do |char2, j|
40
+ cost = (char1 == char2) ? 0 : 1
41
+ x = [
42
+ d[j + 1] + 1, # insertion
43
+ e + 1, # deletion
44
+ d[j] + cost # substitution
45
+ ].min
46
+ d[j] = e
47
+ e = x
48
+ end
49
+
50
+ d[m] = x
51
+ end
52
+
53
+ x
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -26,6 +26,12 @@ module Rails
26
26
  @options = options
27
27
 
28
28
  app.sandbox = sandbox?
29
+
30
+ if sandbox? && app.config.disable_sandbox
31
+ puts "Error: Unable to start console in sandbox mode as sandbox mode is disabled (config.disable_sandbox is true)."
32
+ exit 1
33
+ end
34
+
29
35
  app.load_console
30
36
 
31
37
  @console = app.config.console || IRB
@@ -14,7 +14,7 @@ that just contains the secret_key_base used by MessageVerifiers/MessageEncryptor
14
14
  signing and encrypting cookies.
15
15
 
16
16
  For applications created prior to Rails 5.2, we'll automatically generate a new
17
- credentials file in `config/credentials.yml.enc` the first time you run `bin/rails credentials:edit`.
17
+ credentials file in `config/credentials.yml.enc` the first time you run `rails credentials:edit`.
18
18
  If you didn't have a master key saved in `config/master.key`, that'll be created too.
19
19
 
20
20
  Don't lose this master key! Put it in a password manager your team can access.
@@ -38,3 +38,21 @@ the encrypted credentials.
38
38
  When the temporary file is next saved the contents are encrypted and written to
39
39
  `config/credentials.yml.enc` while the file itself is destroyed to prevent credentials
40
40
  from leaking.
41
+
42
+ === Environment Specific Credentials
43
+
44
+ The `credentials` command supports passing an `--environment` option to create an
45
+ environment specific override. That override will take precedence over the
46
+ global `config/credentials.yml.enc` file when running in that environment. So:
47
+
48
+ rails credentials:edit --environment development
49
+
50
+ will create `config/credentials/development.yml.enc` with the corresponding
51
+ encryption key in `config/credentials/development.key` if the credentials file
52
+ doesn't exist.
53
+
54
+ The encryption key can also be put in `ENV["RAILS_MASTER_KEY"]`, which takes
55
+ precedence over the file encryption key.
56
+
57
+ In addition to that, the default credentials lookup paths can be overridden through
58
+ `config.credentials.content_path` and `config.credentials.key_path`.
@@ -2,11 +2,15 @@
2
2
 
3
3
  require "active_support"
4
4
  require "rails/command/helpers/editor"
5
+ require "rails/command/environment_argument"
5
6
 
6
7
  module Rails
7
8
  module Command
8
9
  class CredentialsCommand < Rails::Command::Base # :nodoc:
9
10
  include Helpers::Editor
11
+ include EnvironmentArgument
12
+
13
+ self.environment_desc = "Uses credentials from config/credentials/:environment.yml.enc encrypted by config/credentials/:environment.key key"
10
14
 
11
15
  no_commands do
12
16
  def help
@@ -17,47 +21,84 @@ module Rails
17
21
  end
18
22
 
19
23
  def edit
24
+ extract_environment_option_from_argument(default_environment: nil)
20
25
  require_application!
21
26
 
22
27
  ensure_editor_available(command: "bin/rails credentials:edit") || (return)
23
- ensure_master_key_has_been_added if Rails.application.credentials.key.nil?
28
+
29
+ ensure_encryption_key_has_been_added if credentials.key.nil?
24
30
  ensure_credentials_have_been_added
25
31
 
26
32
  catch_editing_exceptions do
27
33
  change_credentials_in_system_editor
28
34
  end
29
35
 
30
- say "New credentials encrypted and saved."
36
+ say "File encrypted and saved."
37
+ rescue ActiveSupport::MessageEncryptor::InvalidMessage
38
+ say "Couldn't decrypt #{content_path}. Perhaps you passed the wrong key?"
31
39
  end
32
40
 
33
41
  def show
42
+ extract_environment_option_from_argument(default_environment: nil)
34
43
  require_application!
35
44
 
36
- say Rails.application.credentials.read.presence || missing_credentials_message
45
+ say credentials.read.presence || missing_credentials_message
37
46
  end
38
47
 
39
48
  private
40
- def ensure_master_key_has_been_added
41
- master_key_generator.add_master_key_file
42
- master_key_generator.ignore_master_key_file
49
+ def credentials
50
+ Rails.application.encrypted(content_path, key_path: key_path)
51
+ end
52
+
53
+ def ensure_encryption_key_has_been_added
54
+ encryption_key_file_generator.add_key_file(key_path)
55
+ encryption_key_file_generator.ignore_key_file(key_path)
43
56
  end
44
57
 
45
58
  def ensure_credentials_have_been_added
46
- credentials_generator.add_credentials_file_silently
59
+ if options[:environment]
60
+ encrypted_file_generator.add_encrypted_file_silently(content_path, key_path)
61
+ else
62
+ credentials_generator.add_credentials_file_silently
63
+ end
47
64
  end
48
65
 
49
66
  def change_credentials_in_system_editor
50
- Rails.application.credentials.change do |tmp_path|
67
+ credentials.change do |tmp_path|
51
68
  system("#{ENV["EDITOR"]} #{tmp_path}")
52
69
  end
53
70
  end
54
71
 
72
+ def missing_credentials_message
73
+ if credentials.key.nil?
74
+ "Missing '#{key_path}' to decrypt credentials. See `rails credentials:help`"
75
+ else
76
+ "File '#{content_path}' does not exist. Use `rails credentials:edit` to change that."
77
+ end
78
+ end
79
+
80
+
81
+ def content_path
82
+ options[:environment] ? "config/credentials/#{options[:environment]}.yml.enc" : "config/credentials.yml.enc"
83
+ end
55
84
 
56
- def master_key_generator
85
+ def key_path
86
+ options[:environment] ? "config/credentials/#{options[:environment]}.key" : "config/master.key"
87
+ end
88
+
89
+
90
+ def encryption_key_file_generator
91
+ require "rails/generators"
92
+ require "rails/generators/rails/encryption_key_file/encryption_key_file_generator"
93
+
94
+ Rails::Generators::EncryptionKeyFileGenerator.new
95
+ end
96
+
97
+ def encrypted_file_generator
57
98
  require "rails/generators"
58
- require "rails/generators/rails/master_key/master_key_generator"
99
+ require "rails/generators/rails/encrypted_file/encrypted_file_generator"
59
100
 
60
- Rails::Generators::MasterKeyGenerator.new
101
+ Rails::Generators::EncryptedFileGenerator.new
61
102
  end
62
103
 
63
104
  def credentials_generator
@@ -66,14 +107,6 @@ module Rails
66
107
 
67
108
  Rails::Generators::CredentialsGenerator.new
68
109
  end
69
-
70
- def missing_credentials_message
71
- if Rails.application.credentials.key.nil?
72
- "Missing master key to decrypt credentials. See bin/rails credentials:help"
73
- else
74
- "No credentials have been added yet. Use bin/rails credentials:edit to change that."
75
- end
76
- end
77
110
  end
78
111
  end
79
112
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "rails/generators/rails/db/system/change/change_generator"
5
+
6
+ module Rails
7
+ module Command
8
+ module Db
9
+ module System
10
+ class ChangeCommand < Base # :nodoc:
11
+ class_option :to, desc: "The database system to switch to."
12
+
13
+ def perform
14
+ Rails::Generators::Db::System::ChangeGenerator.start
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end