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
@@ -79,13 +79,7 @@ module Rails
79
79
  end
80
80
 
81
81
  protected
82
- def operations
83
- @operations
84
- end
85
-
86
- def delete_operations
87
- @delete_operations
88
- end
82
+ attr_reader :operations, :delete_operations
89
83
  end
90
84
 
91
85
  class Generators #:nodoc:
@@ -230,7 +230,7 @@ module Rails
230
230
  #
231
231
  # If +MyEngine+ is isolated, The routes above will point to
232
232
  # <tt>MyEngine::ArticlesController</tt>. You also don't need to use longer
233
- # url helpers like +my_engine_articles_path+. Instead, you should simply use
233
+ # URL helpers like +my_engine_articles_path+. Instead, you should simply use
234
234
  # +articles_path+, like you would do with your main application.
235
235
  #
236
236
  # To make this behavior consistent with other parts of the framework,
@@ -238,7 +238,7 @@ module Rails
238
238
  # normal Rails app, when you use a namespaced model such as
239
239
  # <tt>Namespace::Article</tt>, <tt>ActiveModel::Naming</tt> will generate
240
240
  # names with the prefix "namespace". In an isolated engine, the prefix will
241
- # be omitted in url helpers and form fields, for convenience.
241
+ # be omitted in URL helpers and form fields, for convenience.
242
242
  #
243
243
  # polymorphic_url(MyEngine::Article.new)
244
244
  # # => "articles_path" # not "my_engine_articles_path"
@@ -286,11 +286,11 @@ module Rails
286
286
  # Note that the <tt>:as</tt> option given to mount takes the <tt>engine_name</tt> as default, so most of the time
287
287
  # you can simply omit it.
288
288
  #
289
- # Finally, if you want to generate a url to an engine's route using
289
+ # Finally, if you want to generate a URL to an engine's route using
290
290
  # <tt>polymorphic_url</tt>, you also need to pass the engine helper. Let's
291
291
  # say that you want to create a form pointing to one of the engine's routes.
292
292
  # All you need to do is pass the helper as the first element in array with
293
- # attributes for url:
293
+ # attributes for URL:
294
294
  #
295
295
  # form_for([my_engine, @user])
296
296
  #
@@ -469,13 +469,15 @@ module Rails
469
469
  self
470
470
  end
471
471
 
472
- # Eager load the application by loading all ruby
473
- # files inside eager_load paths.
474
472
  def eager_load!
473
+ # Already done by Zeitwerk::Loader.eager_load_all in the finisher.
474
+ return if Rails.autoloaders.zeitwerk_enabled?
475
+
475
476
  config.eager_load_paths.each do |load_path|
476
- matcher = /\A#{Regexp.escape(load_path.to_s)}\/(.*)\.rb\Z/
477
+ # Starts after load_path plus a slash, ends before ".rb".
478
+ relname_range = (load_path.to_s.length + 1)...-3
477
479
  Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
478
- require_dependency file.sub(matcher, '\1')
480
+ require_dependency file[relname_range]
479
481
  end
480
482
  end
481
483
  end
@@ -550,16 +552,15 @@ module Rails
550
552
  seed_file = paths["db/seeds.rb"].existent.first
551
553
  return unless seed_file
552
554
 
553
- if config.try(:active_job).try!(:queue_adapter) == :async
555
+ if config.try(:active_job)&.queue_adapter == :async
554
556
  with_inline_jobs { load(seed_file) }
555
557
  else
556
558
  load(seed_file)
557
559
  end
558
560
  end
559
561
 
560
- # Add configured load paths to Ruby's load path, and remove duplicate entries.
561
- initializer :set_load_path, before: :bootstrap_hook do
562
- _all_load_paths.reverse_each do |path|
562
+ initializer :set_load_path, before: :bootstrap_hook do |app|
563
+ _all_load_paths(app.config.add_autoload_paths_to_load_path).reverse_each do |path|
563
564
  $LOAD_PATH.unshift(path) if File.directory?(path)
564
565
  end
565
566
  $LOAD_PATH.uniq!
@@ -574,12 +575,15 @@ module Rails
574
575
  ActiveSupport::Dependencies.autoload_paths.unshift(*_all_autoload_paths)
575
576
  ActiveSupport::Dependencies.autoload_once_paths.unshift(*_all_autoload_once_paths)
576
577
 
577
- # Freeze so future modifications will fail rather than do nothing mysteriously
578
578
  config.autoload_paths.freeze
579
- config.eager_load_paths.freeze
580
579
  config.autoload_once_paths.freeze
581
580
  end
582
581
 
582
+ initializer :set_eager_load_paths, before: :bootstrap_hook do
583
+ ActiveSupport::Dependencies._eager_load_paths.merge(config.eager_load_paths)
584
+ config.eager_load_paths.freeze
585
+ end
586
+
583
587
  initializer :add_routing_paths do |app|
584
588
  routing_paths = paths["config/routes.rb"].existent
585
589
 
@@ -704,8 +708,12 @@ module Rails
704
708
  @_all_autoload_paths ||= (config.autoload_paths + config.eager_load_paths + config.autoload_once_paths).uniq
705
709
  end
706
710
 
707
- def _all_load_paths
708
- @_all_load_paths ||= (config.paths.load_paths + _all_autoload_paths).uniq
711
+ def _all_load_paths(add_autoload_paths_to_load_path)
712
+ @_all_load_paths ||= begin
713
+ load_paths = config.paths.load_paths
714
+ load_paths += _all_autoload_paths if add_autoload_paths_to_load_path
715
+ load_paths.uniq
716
+ end
709
717
  end
710
718
 
711
719
  def build_request(env)
@@ -6,7 +6,7 @@ module Rails
6
6
  class Engine
7
7
  class Configuration < ::Rails::Railtie::Configuration
8
8
  attr_reader :root
9
- attr_accessor :middleware
9
+ attr_accessor :middleware, :javascript_path
10
10
  attr_writer :eager_load_paths, :autoload_once_paths, :autoload_paths
11
11
 
12
12
  def initialize(root = nil)
@@ -14,6 +14,7 @@ module Rails
14
14
  @root = root
15
15
  @generators = app_generators.dup
16
16
  @middleware = Rails::Configuration::MiddlewareStackProxy.new
17
+ @javascript_path = "javascript"
17
18
  end
18
19
 
19
20
  # Holds generators configuration:
@@ -38,7 +39,9 @@ module Rails
38
39
  @paths ||= begin
39
40
  paths = Rails::Paths::Root.new(@root)
40
41
 
41
- paths.add "app", eager_load: true, glob: "{*,*/concerns}"
42
+ paths.add "app", eager_load: true,
43
+ glob: "{*,*/concerns}",
44
+ exclude: ["assets", javascript_path]
42
45
  paths.add "app/assets", glob: "*"
43
46
  paths.add "app/controllers", eager_load: true
44
47
  paths.add "app/channels", eager_load: true, glob: "**/*_channel.rb"
@@ -7,9 +7,9 @@ module Rails
7
7
  end
8
8
 
9
9
  module VERSION
10
- MAJOR = 5
11
- MINOR = 2
12
- TINY = 4
10
+ MAJOR = 6
11
+ MINOR = 0
12
+ TINY = 0
13
13
  PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -23,6 +23,8 @@ module Rails
23
23
  autoload :ActiveModel, "rails/generators/active_model"
24
24
  autoload :Base, "rails/generators/base"
25
25
  autoload :Migration, "rails/generators/migration"
26
+ autoload :Database, "rails/generators/database"
27
+ autoload :AppName, "rails/generators/app_name"
26
28
  autoload :NamedBase, "rails/generators/named_base"
27
29
  autoload :ResourceHelpers, "rails/generators/resource_helpers"
28
30
  autoload :TestCase, "rails/generators/test_case"
@@ -56,8 +58,6 @@ module Rails
56
58
  force_plural: false,
57
59
  helper: true,
58
60
  integration_tool: nil,
59
- javascripts: true,
60
- javascript_engine: :js,
61
61
  orm: false,
62
62
  resource_controller: :controller,
63
63
  resource_route: true,
@@ -126,7 +126,7 @@ module Rails
126
126
  )
127
127
 
128
128
  if ARGV.first == "mailer"
129
- options[:rails].merge!(template_engine: :erb)
129
+ options[:rails][:template_engine] = :erb
130
130
  end
131
131
  end
132
132
 
@@ -222,6 +222,7 @@ module Rails
222
222
  rails.delete("encryption_key_file")
223
223
  rails.delete("master_key")
224
224
  rails.delete("credentials")
225
+ rails.delete("db:system:change")
225
226
 
226
227
  hidden_namespaces.each { |n| groups.delete(n.to_s) }
227
228
 
@@ -258,7 +259,6 @@ module Rails
258
259
 
259
260
  namespaces = Hash[subclasses.map { |klass| [klass.namespace, klass] }]
260
261
  lookups.each do |namespace|
261
-
262
262
  klass = namespaces[namespace]
263
263
  return klass if klass
264
264
  end
@@ -276,12 +276,13 @@ module Rails
276
276
  klass.start(args, config)
277
277
  else
278
278
  options = sorted_groups.flat_map(&:last)
279
- suggestions = options.sort_by { |suggested| levenshtein_distance(namespace.to_s, suggested) }.first(3)
280
- suggestions.map! { |s| "'#{s}'" }
281
- msg = "Could not find generator '#{namespace}'. ".dup
282
- msg << "Maybe you meant #{ suggestions[0...-1].join(', ')} or #{suggestions[-1]}\n"
283
- msg << "Run `rails generate --help` for more options."
284
- puts msg
279
+ suggestion = Rails::Command::Spellchecker.suggest(namespace.to_s, from: options)
280
+ suggestion_msg = "Maybe you meant #{suggestion.inspect}?" if suggestion
281
+
282
+ puts <<~MSG
283
+ Could not find generator '#{namespace}'. #{suggestion_msg}
284
+ Run `rails generate --help` for more options.
285
+ MSG
285
286
  end
286
287
  end
287
288
 
@@ -1,12 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/string/strip"
4
+
3
5
  module Rails
4
6
  module Generators
5
7
  module Actions
6
8
  def initialize(*) # :nodoc:
7
9
  super
8
- @in_group = nil
9
- @after_bundle_callbacks = []
10
+ @indentation = 0
10
11
  end
11
12
 
12
13
  # Adds an entry into +Gemfile+ for the supplied gem.
@@ -34,13 +35,11 @@ module Rails
34
35
 
35
36
  log :gemfile, message
36
37
 
37
- options.each do |option, value|
38
- parts << "#{option}: #{quote(value)}"
39
- end
38
+ parts << quote(options) unless options.empty?
40
39
 
41
40
  in_root do
42
41
  str = "gem #{parts.join(", ")}"
43
- str = " " + str if @in_group
42
+ str = indentation + str
44
43
  str = "\n" + str
45
44
  append_file "Gemfile", str, verbose: false
46
45
  end
@@ -52,17 +51,29 @@ module Rails
52
51
  # gem "rspec-rails"
53
52
  # end
54
53
  def gem_group(*names, &block)
55
- name = names.map(&:inspect).join(", ")
56
- log :gemfile, "group #{name}"
54
+ options = names.extract_options!
55
+ str = names.map(&:inspect)
56
+ str << quote(options) unless options.empty?
57
+ str = str.join(", ")
58
+ log :gemfile, "group #{str}"
57
59
 
58
60
  in_root do
59
- append_file "Gemfile", "\ngroup #{name} do", force: true
61
+ append_file "Gemfile", "\ngroup #{str} do", force: true
62
+ with_indentation(&block)
63
+ append_file "Gemfile", "\nend\n", force: true
64
+ end
65
+ end
60
66
 
61
- @in_group = true
62
- instance_eval(&block)
63
- @in_group = false
67
+ def github(repo, options = {}, &block)
68
+ str = [quote(repo)]
69
+ str << quote(options) unless options.empty?
70
+ str = str.join(", ")
71
+ log :github, "github #{str}"
64
72
 
65
- append_file "Gemfile", "\nend\n", force: true
73
+ in_root do
74
+ append_file "Gemfile", "\n#{indentation}github #{str} do", force: true
75
+ with_indentation(&block)
76
+ append_file "Gemfile", "\n#{indentation}end", force: true
66
77
  end
67
78
  end
68
79
 
@@ -81,9 +92,7 @@ module Rails
81
92
  in_root do
82
93
  if block
83
94
  append_file "Gemfile", "\nsource #{quote(source)} do", force: true
84
- @in_group = true
85
- instance_eval(&block)
86
- @in_group = false
95
+ with_indentation(&block)
87
96
  append_file "Gemfile", "\nend\n", force: true
88
97
  else
89
98
  prepend_file "Gemfile", "source #{quote(source)}\n", verbose: false
@@ -211,9 +220,12 @@ module Rails
211
220
  # generate(:authenticated, "user session")
212
221
  def generate(what, *args)
213
222
  log :generate, what
223
+
224
+ options = args.extract_options!
225
+ options[:without_rails_env] = true
214
226
  argument = args.flat_map(&:to_s).join(" ")
215
227
 
216
- in_root { run_ruby_script("bin/rails generate #{what} #{argument}", verbose: false) }
228
+ execute_command :rails, "generate #{what} #{argument}", options
217
229
  end
218
230
 
219
231
  # Runs the supplied rake task (invoked with 'rake ...')
@@ -236,15 +248,6 @@ module Rails
236
248
  execute_command :rails, command, options
237
249
  end
238
250
 
239
- # Just run the capify command in root
240
- #
241
- # capify!
242
- def capify!
243
- ActiveSupport::Deprecation.warn("`capify!` is deprecated and will be removed in the next version of Rails.")
244
- log :capify, ""
245
- in_root { run("#{extify(:capify)} .", verbose: false) }
246
- end
247
-
248
251
  # Make an entry in Rails routing file <tt>config/routes.rb</tt>
249
252
  #
250
253
  # route "root 'welcome#index'"
@@ -264,16 +267,6 @@ module Rails
264
267
  log File.read(find_in_source_paths(path))
265
268
  end
266
269
 
267
- # Registers a callback to be executed after bundle and spring binstubs
268
- # have run.
269
- #
270
- # after_bundle do
271
- # git add: '.'
272
- # end
273
- def after_bundle(&block)
274
- @after_bundle_callbacks << block
275
- end
276
-
277
270
  private
278
271
 
279
272
  # Define log for backwards compatibility. If just one argument is sent,
@@ -292,13 +285,15 @@ module Rails
292
285
  # based on the executor parameter provided.
293
286
  def execute_command(executor, command, options = {}) # :doc:
294
287
  log executor, command
295
- env = options[:env] || ENV["RAILS_ENV"] || "development"
288
+ env = options[:env] || ENV["RAILS_ENV"] || "development"
289
+ rails_env = " RAILS_ENV=#{env}" unless options[:without_rails_env]
296
290
  sudo = options[:sudo] && !Gem.win_platform? ? "sudo " : ""
297
291
  config = { verbose: false }
298
292
 
299
- config.merge!(capture: options[:capture]) if options[:capture]
293
+ config[:capture] = options[:capture] if options[:capture]
294
+ config[:abort_on_failure] = options[:abort_on_failure] if options[:abort_on_failure]
300
295
 
301
- in_root { run("#{sudo}#{extify(executor)} #{command} RAILS_ENV=#{env}", config) }
296
+ in_root { run("#{sudo}#{extify(executor)} #{command}#{rails_env}", config) }
302
297
  end
303
298
 
304
299
  # Add an extension to the given name based on the platform.
@@ -313,6 +308,11 @@ module Rails
313
308
  # Surround string with single quotes if there is no quotes.
314
309
  # Otherwise fall back to double quotes
315
310
  def quote(value) # :doc:
311
+ if value.respond_to? :each_pair
312
+ return value.map do |k, v|
313
+ "#{k}: #{quote(v)}"
314
+ end.join(", ")
315
+ end
316
316
  return value.inspect unless value.is_a? String
317
317
 
318
318
  if value.include?("'")
@@ -332,6 +332,19 @@ module Rails
332
332
  "#{value.strip.indent(amount)}\n"
333
333
  end
334
334
  end
335
+
336
+ # Indent the +Gemfile+ to the depth of @indentation
337
+ def indentation # :doc:
338
+ " " * @indentation
339
+ end
340
+
341
+ # Manage +Gemfile+ indentation for a DSL action block
342
+ def with_indentation(&block) # :doc:
343
+ @indentation += 1
344
+ instance_eval(&block)
345
+ ensure
346
+ @indentation -= 1
347
+ end
335
348
  end
336
349
  end
337
350
  end
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "fileutils"
4
4
  require "digest/md5"
5
- require "active_support/core_ext/string/strip"
6
5
  require "rails/version" unless defined?(Rails::VERSION)
7
6
  require "open-uri"
8
7
  require "uri"
@@ -12,9 +11,8 @@ require "active_support/core_ext/array/extract_options"
12
11
  module Rails
13
12
  module Generators
14
13
  class AppBase < Base # :nodoc:
15
- DATABASES = %w( mysql postgresql sqlite3 oracle frontbase ibm_db sqlserver )
16
- JDBC_DATABASES = %w( jdbcmysql jdbcsqlite3 jdbcpostgresql jdbc )
17
- DATABASES.concat(JDBC_DATABASES)
14
+ include Database
15
+ include AppName
18
16
 
19
17
  attr_accessor :rails_template
20
18
  add_shebang_option!
@@ -32,9 +30,6 @@ module Rails
32
30
  class_option :database, type: :string, aliases: "-d", default: "sqlite3",
33
31
  desc: "Preconfigure for selected database (options: #{DATABASES.join('/')})"
34
32
 
35
- class_option :skip_yarn, type: :boolean, default: false,
36
- desc: "Don't use Yarn for managing JavaScript dependencies"
37
-
38
33
  class_option :skip_gemfile, type: :boolean, default: false,
39
34
  desc: "Don't create a Gemfile"
40
35
 
@@ -48,6 +43,12 @@ module Rails
48
43
  default: false,
49
44
  desc: "Skip Action Mailer files"
50
45
 
46
+ class_option :skip_action_mailbox, type: :boolean, default: false,
47
+ desc: "Skip Action Mailbox gem"
48
+
49
+ class_option :skip_action_text, type: :boolean, default: false,
50
+ desc: "Skip Action Text gem"
51
+
51
52
  class_option :skip_active_record, type: :boolean, aliases: "-O", default: false,
52
53
  desc: "Skip Active Record files"
53
54
 
@@ -69,10 +70,7 @@ module Rails
69
70
  class_option :skip_listen, type: :boolean, default: false,
70
71
  desc: "Don't generate configuration that depends on the listen gem"
71
72
 
72
- class_option :skip_coffee, type: :boolean, default: false,
73
- desc: "Don't use CoffeeScript"
74
-
75
- class_option :skip_javascript, type: :boolean, aliases: "-J", default: false,
73
+ class_option :skip_javascript, type: :boolean, aliases: "-J", default: name == "plugin",
76
74
  desc: "Skip JavaScript files"
77
75
 
78
76
  class_option :skip_turbolinks, type: :boolean, default: false,
@@ -107,7 +105,6 @@ module Rails
107
105
  @gem_filter = lambda { |gem| true }
108
106
  @extra_entries = []
109
107
  super
110
- convert_database_option_for_jruby
111
108
  end
112
109
 
113
110
  private
@@ -131,7 +128,7 @@ module Rails
131
128
  def gemfile_entries # :doc:
132
129
  [rails_gemfile_entry,
133
130
  database_gemfile_entry,
134
- webserver_gemfile_entry,
131
+ web_server_gemfile_entry,
135
132
  assets_gemfile_entry,
136
133
  webpacker_gemfile_entry,
137
134
  javascript_gemfile_entry,
@@ -192,7 +189,7 @@ module Rails
192
189
  "Use #{options[:database]} as the database for Active Record"
193
190
  end
194
191
 
195
- def webserver_gemfile_entry # :doc:
192
+ def web_server_gemfile_entry # :doc:
196
193
  return [] if options[:skip_puma]
197
194
  comment = "Use Puma as the app server"
198
195
  GemfileEntry.new("puma", "~> 3.11", comment)
@@ -207,7 +204,9 @@ module Rails
207
204
  :skip_sprockets,
208
205
  :skip_action_cable
209
206
  ),
210
- skip_active_storage?
207
+ skip_active_storage?,
208
+ skip_action_mailbox?,
209
+ skip_action_text?
211
210
  ].flatten.none?
212
211
  end
213
212
 
@@ -236,6 +235,14 @@ module Rails
236
235
  options[:skip_active_storage] || options[:skip_active_record]
237
236
  end
238
237
 
238
+ def skip_action_mailbox? # :doc:
239
+ options[:skip_action_mailbox] || skip_active_storage?
240
+ end
241
+
242
+ def skip_action_text? # :doc:
243
+ options[:skip_action_text] || skip_active_storage?
244
+ end
245
+
239
246
  class GemfileEntry < Struct.new(:name, :version, :comment, :options, :commented_out)
240
247
  def initialize(name, version, comment, options = {}, commented_out = false)
241
248
  super
@@ -275,7 +282,7 @@ module Rails
275
282
  ]
276
283
  elsif options.edge?
277
284
  [
278
- GemfileEntry.github("rails", "rails/rails", "5-2-stable")
285
+ GemfileEntry.github("rails", "rails/rails", "6-0-stable")
279
286
  ]
280
287
  else
281
288
  [GemfileEntry.version("rails",
@@ -297,90 +304,33 @@ module Rails
297
304
  end
298
305
  end
299
306
 
300
- def gem_for_database
301
- # %w( mysql postgresql sqlite3 oracle frontbase ibm_db sqlserver jdbcmysql jdbcsqlite3 jdbcpostgresql )
302
- case options[:database]
303
- when "mysql" then ["mysql2", [">= 0.4.4", "< 0.6.0"]]
304
- when "postgresql" then ["pg", [">= 0.18", "< 2.0"]]
305
- when "oracle" then ["activerecord-oracle_enhanced-adapter", nil]
306
- when "frontbase" then ["ruby-frontbase", nil]
307
- when "sqlserver" then ["activerecord-sqlserver-adapter", nil]
308
- when "jdbcmysql" then ["activerecord-jdbcmysql-adapter", nil]
309
- when "jdbcsqlite3" then ["activerecord-jdbcsqlite3-adapter", nil]
310
- when "jdbcpostgresql" then ["activerecord-jdbcpostgresql-adapter", nil]
311
- when "jdbc" then ["activerecord-jdbc-adapter", nil]
312
- else [options[:database], nil]
313
- end
314
- end
315
-
316
- def convert_database_option_for_jruby
317
- if defined?(JRUBY_VERSION)
318
- opt = options.dup
319
- case opt[:database]
320
- when "postgresql" then opt[:database] = "jdbcpostgresql"
321
- when "mysql" then opt[:database] = "jdbcmysql"
322
- when "sqlite3" then opt[:database] = "jdbcsqlite3"
323
- end
324
- self.options = opt.freeze
325
- end
326
- end
327
-
328
307
  def assets_gemfile_entry
329
308
  return [] if options[:skip_sprockets]
330
309
 
331
- gems = []
332
- gems << GemfileEntry.version("sass-rails", "~> 5.0",
333
- "Use SCSS for stylesheets")
334
-
335
- if !options[:skip_javascript]
336
- gems << GemfileEntry.version("uglifier",
337
- ">= 1.3.0",
338
- "Use Uglifier as compressor for JavaScript assets")
339
- end
340
-
341
- gems
310
+ GemfileEntry.version("sass-rails", "~> 5", "Use SCSS for stylesheets")
342
311
  end
343
312
 
344
313
  def webpacker_gemfile_entry
345
- return [] unless options[:webpack]
314
+ return [] if options[:skip_javascript]
346
315
 
347
- comment = "Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker"
348
- GemfileEntry.new "webpacker", nil, comment
316
+ if options.dev? || options.edge?
317
+ GemfileEntry.github "webpacker", "rails/webpacker", nil, "Use development version of Webpacker"
318
+ else
319
+ GemfileEntry.version "webpacker", "~> 4.0", "Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker"
320
+ end
349
321
  end
350
322
 
351
323
  def jbuilder_gemfile_entry
352
324
  comment = "Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder"
353
- GemfileEntry.new "jbuilder", "~> 2.5", comment, {}, options[:api]
354
- end
355
-
356
- def coffee_gemfile_entry
357
- GemfileEntry.version "coffee-rails", "~> 4.2", "Use CoffeeScript for .coffee assets and views"
325
+ GemfileEntry.new "jbuilder", "~> 2.7", comment, {}, options[:api]
358
326
  end
359
327
 
360
328
  def javascript_gemfile_entry
361
- if options[:skip_javascript] || options[:skip_sprockets]
329
+ if options[:skip_javascript] || options[:skip_turbolinks]
362
330
  []
363
331
  else
364
- gems = [javascript_runtime_gemfile_entry]
365
- gems << coffee_gemfile_entry unless options[:skip_coffee]
366
-
367
- unless options[:skip_turbolinks]
368
- gems << GemfileEntry.version("turbolinks", "~> 5",
369
- "Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks")
370
- end
371
-
372
- gems
373
- end
374
- end
375
-
376
- def javascript_runtime_gemfile_entry
377
- comment = "See https://github.com/rails/execjs#readme for more supported runtimes"
378
- if defined?(JRUBY_VERSION)
379
- GemfileEntry.version "therubyrhino", nil, comment
380
- elsif RUBY_PLATFORM =~ /mingw|mswin/
381
- GemfileEntry.version "duktape", nil, comment
382
- else
383
- GemfileEntry.new "mini_racer", nil, comment, { platforms: :ruby }, true
332
+ [ GemfileEntry.version("turbolinks", "~> 5",
333
+ "Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks") ]
384
334
  end
385
335
  end
386
336
 
@@ -400,7 +350,7 @@ module Rails
400
350
  gems
401
351
  end
402
352
 
403
- def bundle_command(command)
353
+ def bundle_command(command, env = {})
404
354
  say_status :run, "bundle #{command}"
405
355
 
406
356
  # We are going to shell out rather than invoking Bundler::CLI.new(command)
@@ -413,16 +363,16 @@ module Rails
413
363
 
414
364
  require "bundler"
415
365
  Bundler.with_original_env do
416
- exec_bundle_command(_bundle_command, command)
366
+ exec_bundle_command(_bundle_command, command, env)
417
367
  end
418
368
  end
419
369
 
420
- def exec_bundle_command(bundle_command, command)
370
+ def exec_bundle_command(bundle_command, command, env)
421
371
  full_command = %Q["#{Gem.ruby}" "#{bundle_command}" #{command}]
422
372
  if options[:quiet]
423
- system(full_command, out: File::NULL)
373
+ system(env, full_command, out: File::NULL)
424
374
  else
425
- system(full_command)
375
+ system(env, full_command)
426
376
  end
427
377
  end
428
378
 
@@ -434,6 +384,10 @@ module Rails
434
384
  !options[:skip_spring] && !options.dev? && Process.respond_to?(:fork) && !RUBY_PLATFORM.include?("cygwin")
435
385
  end
436
386
 
387
+ def webpack_install?
388
+ !(options[:skip_javascript] || options[:skip_webpack_install])
389
+ end
390
+
437
391
  def depends_on_system_test?
438
392
  !(options[:skip_system_test] || options[:skip_test] || options[:api])
439
393
  end
@@ -451,13 +405,19 @@ module Rails
451
405
  end
452
406
 
453
407
  def run_bundle
454
- bundle_command("install") if bundle_install?
408
+ bundle_command("install", "BUNDLE_IGNORE_MESSAGES" => "1") if bundle_install?
455
409
  end
456
410
 
457
411
  def run_webpack
458
- if !(webpack = options[:webpack]).nil?
412
+ if webpack_install?
459
413
  rails_command "webpacker:install"
460
- rails_command "webpacker:install:#{webpack}" unless webpack == "webpack"
414
+ rails_command "webpacker:install:#{options[:webpack]}" if options[:webpack] && options[:webpack] != "webpack"
415
+ end
416
+ end
417
+
418
+ def generate_bundler_binstub
419
+ if bundle_install?
420
+ bundle_command("binstubs bundler")
461
421
  end
462
422
  end
463
423