railties 7.1.0 → 7.2.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +203 -650
  3. data/lib/minitest/rails_plugin.rb +5 -2
  4. data/lib/rails/all.rb +1 -3
  5. data/lib/rails/api/task.rb +6 -4
  6. data/lib/rails/application/bootstrap.rb +11 -8
  7. data/lib/rails/application/configuration.rb +80 -36
  8. data/lib/rails/application/dummy_config.rb +2 -2
  9. data/lib/rails/application/finisher.rb +10 -0
  10. data/lib/rails/application.rb +29 -76
  11. data/lib/rails/backtrace_cleaner.rb +18 -3
  12. data/lib/rails/cli.rb +0 -1
  13. data/lib/rails/command.rb +1 -1
  14. data/lib/rails/commands/app/update_command.rb +102 -0
  15. data/lib/rails/commands/boot/boot_command.rb +14 -0
  16. data/lib/rails/commands/console/console_command.rb +2 -21
  17. data/lib/rails/commands/console/irb_console.rb +146 -0
  18. data/lib/rails/commands/credentials/USAGE +1 -1
  19. data/lib/rails/commands/credentials/credentials_command.rb +2 -2
  20. data/lib/rails/commands/dbconsole/dbconsole_command.rb +21 -30
  21. data/lib/rails/commands/devcontainer/devcontainer_command.rb +39 -0
  22. data/lib/rails/commands/rake/rake_command.rb +1 -1
  23. data/lib/rails/commands/runner/runner_command.rb +14 -3
  24. data/lib/rails/commands/server/server_command.rb +5 -3
  25. data/lib/rails/commands/test/test_command.rb +2 -0
  26. data/lib/rails/configuration.rb +10 -1
  27. data/lib/rails/console/app.rb +5 -32
  28. data/lib/rails/console/helpers.rb +5 -16
  29. data/lib/rails/console/methods.rb +23 -0
  30. data/lib/rails/engine/configuration.rb +45 -6
  31. data/lib/rails/engine.rb +24 -17
  32. data/lib/rails/gem_version.rb +3 -3
  33. data/lib/rails/generators/active_model.rb +26 -12
  34. data/lib/rails/generators/app_base.rb +80 -61
  35. data/lib/rails/generators/base.rb +9 -5
  36. data/lib/rails/generators/database.rb +227 -69
  37. data/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt +2 -0
  38. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +2 -0
  39. data/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt +2 -0
  40. data/lib/rails/generators/generated_attribute.rb +26 -1
  41. data/lib/rails/generators/migration.rb +3 -3
  42. data/lib/rails/generators/rails/app/app_generator.rb +57 -32
  43. data/lib/rails/generators/rails/app/templates/Dockerfile.tt +23 -16
  44. data/lib/rails/generators/rails/app/templates/Gemfile.tt +17 -17
  45. data/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt +4 -0
  46. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +8 -1
  47. data/lib/rails/generators/rails/app/templates/app/views/pwa/manifest.json.erb.tt +22 -0
  48. data/lib/rails/generators/rails/app/templates/app/views/pwa/service-worker.js +26 -0
  49. data/lib/rails/generators/rails/app/templates/bin/brakeman.tt +6 -0
  50. data/lib/rails/generators/rails/app/templates/bin/rubocop.tt +7 -0
  51. data/lib/rails/generators/rails/app/templates/bin/setup.tt +6 -2
  52. data/lib/rails/generators/rails/app/templates/config/application.rb.tt +1 -1
  53. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +3 -3
  54. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +11 -4
  55. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +8 -1
  56. data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +3 -3
  57. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +14 -7
  58. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +14 -6
  59. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +10 -7
  60. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +1 -1
  61. data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +3 -3
  62. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_2.rb.tt +70 -0
  63. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +25 -26
  64. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +6 -0
  65. data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +5 -0
  66. data/lib/rails/generators/rails/app/templates/dockerignore.tt +13 -0
  67. data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +138 -0
  68. data/lib/rails/generators/rails/app/templates/github/dependabot.yml +12 -0
  69. data/lib/rails/generators/rails/app/templates/gitignore.tt +3 -3
  70. data/lib/rails/generators/rails/app/templates/public/406-unsupported-browser.html +66 -0
  71. data/lib/rails/generators/rails/app/templates/public/icon.png +0 -0
  72. data/lib/rails/generators/rails/app/templates/public/icon.svg +3 -0
  73. data/lib/rails/generators/rails/app/templates/rubocop.yml.tt +8 -0
  74. data/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt +1 -1
  75. data/lib/rails/generators/rails/controller/controller_generator.rb +1 -1
  76. data/lib/rails/generators/rails/db/system/change/change_generator.rb +134 -20
  77. data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +166 -0
  78. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/Dockerfile.tt +3 -0
  79. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/compose.yaml.tt +47 -0
  80. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +37 -0
  81. data/lib/rails/generators/rails/migration/migration_generator.rb +4 -0
  82. data/lib/rails/generators/rails/plugin/plugin_generator.rb +40 -7
  83. data/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt +2 -2
  84. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +5 -1
  85. data/lib/rails/generators/rails/plugin/templates/app/views/layouts/%namespaced_name%/application.html.erb.tt +2 -0
  86. data/lib/rails/generators/rails/plugin/templates/bin/rubocop.tt +7 -0
  87. data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +103 -0
  88. data/lib/rails/generators/rails/plugin/templates/github/dependabot.yml +12 -0
  89. data/lib/rails/generators/rails/plugin/templates/rubocop.yml.tt +8 -0
  90. data/lib/rails/generators/rails/plugin/templates/test/application_system_test_case.rb.tt +1 -1
  91. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +2 -2
  92. data/lib/rails/generators/test_unit/mailer/templates/functional_test.rb.tt +6 -4
  93. data/lib/rails/generators/test_unit/mailer/templates/preview.rb.tt +3 -2
  94. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +15 -1
  95. data/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt +2 -2
  96. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt +2 -2
  97. data/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt +2 -0
  98. data/lib/rails/generators/test_unit/system/templates/application_system_test_case.rb.tt +1 -1
  99. data/lib/rails/generators/testing/assertions.rb +20 -0
  100. data/lib/rails/generators/testing/behavior.rb +7 -6
  101. data/lib/rails/generators.rb +7 -3
  102. data/lib/rails/health_controller.rb +2 -2
  103. data/lib/rails/info.rb +2 -2
  104. data/lib/rails/info_controller.rb +4 -2
  105. data/lib/rails/mailers_controller.rb +14 -1
  106. data/lib/rails/paths.rb +2 -2
  107. data/lib/rails/pwa_controller.rb +15 -0
  108. data/lib/rails/rack/logger.rb +15 -7
  109. data/lib/rails/railtie/configurable.rb +2 -2
  110. data/lib/rails/railtie.rb +15 -16
  111. data/lib/rails/tasks/framework.rake +0 -26
  112. data/lib/rails/tasks/tmp.rake +1 -1
  113. data/lib/rails/tasks/zeitwerk.rake +14 -34
  114. data/lib/rails/templates/layouts/application.html.erb +1 -1
  115. data/lib/rails/templates/rails/mailers/email.html.erb +20 -9
  116. data/lib/rails/templates/rails/welcome/index.html.erb +4 -2
  117. data/lib/rails/test_help.rb +2 -4
  118. data/lib/rails/test_unit/reporter.rb +8 -2
  119. data/lib/rails/test_unit/runner.rb +26 -2
  120. data/lib/rails/test_unit/test_parser.rb +45 -0
  121. data/lib/rails/testing/maintain_test_schema.rb +1 -1
  122. data/lib/rails/zeitwerk_checker.rb +15 -0
  123. data/lib/rails.rb +7 -4
  124. metadata +46 -35
  125. data/lib/rails/app_updater.rb +0 -40
  126. data/lib/rails/commands/secrets/USAGE +0 -61
  127. data/lib/rails/commands/secrets/secrets_command.rb +0 -46
  128. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +0 -68
  129. data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt +0 -54
  130. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +0 -70
  131. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +0 -24
  132. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +0 -62
  133. data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +0 -53
  134. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_1.rb.tt +0 -223
  135. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon-precomposed.png +0 -0
  136. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon.png +0 -0
  137. data/lib/rails/generators/rails/app/templates/public/favicon.ico +0 -0
  138. data/lib/rails/ruby_version_check.rb +0 -17
  139. data/lib/rails/secrets.rb +0 -110
@@ -9,12 +9,45 @@ module Rails
9
9
  attr_accessor :middleware, :javascript_path
10
10
  attr_writer :eager_load_paths, :autoload_once_paths, :autoload_paths
11
11
 
12
+ # An array of custom autoload paths to be added to the ones defined
13
+ # automatically by Rails. These won't be eager loaded, unless you push
14
+ # them to +eager_load_paths+ too, which is recommended.
15
+ #
16
+ # This collection is empty by default, it accepts strings and +Pathname+
17
+ # objects.
18
+ #
19
+ # If you'd like to add +lib+ to it, please see +autoload_lib+.
20
+ attr_reader :autoload_paths
21
+
22
+ # An array of custom autoload once paths. These won't be eager loaded
23
+ # unless you push them to +eager_load_paths+ too, which is recommended.
24
+ #
25
+ # This collection is empty by default, it accepts strings and +Pathname+
26
+ # objects.
27
+ #
28
+ # If you'd like to add +lib+ to it, please see +autoload_lib_once+.
29
+ attr_reader :autoload_once_paths
30
+
31
+ # An array of custom eager load paths to be added to the ones defined
32
+ # automatically by Rails. Anything in this collection is considered to be
33
+ # an autoload path regardless of whether it was added to +autoload_paths+.
34
+ #
35
+ # This collection is empty by default, it accepts strings and +Pathname+
36
+ # objects.
37
+ #
38
+ # If you'd like to add +lib+ to it, please see +autoload_lib+.
39
+ attr_reader :eager_load_paths
40
+
12
41
  def initialize(root = nil)
13
42
  super()
14
43
  @root = root
15
44
  @generators = app_generators.dup
16
45
  @middleware = Rails::Configuration::MiddlewareStackProxy.new
17
46
  @javascript_path = "javascript"
47
+
48
+ @autoload_paths = []
49
+ @autoload_once_paths = []
50
+ @eager_load_paths = []
18
51
  end
19
52
 
20
53
  # Holds generators configuration:
@@ -81,16 +114,22 @@ module Rails
81
114
  @root = paths.path = Pathname.new(value).expand_path
82
115
  end
83
116
 
84
- def eager_load_paths
85
- @eager_load_paths ||= paths.eager_load
117
+ # Private method that adds custom autoload paths to the ones defined by
118
+ # +paths+.
119
+ def all_autoload_paths # :nodoc:
120
+ autoload_paths + paths.autoload_paths
86
121
  end
87
122
 
88
- def autoload_once_paths
89
- @autoload_once_paths ||= paths.autoload_once
123
+ # Private method that adds custom autoload once paths to the ones defined
124
+ # by +paths+.
125
+ def all_autoload_once_paths # :nodoc:
126
+ autoload_once_paths + paths.autoload_once
90
127
  end
91
128
 
92
- def autoload_paths
93
- @autoload_paths ||= paths.autoload_paths
129
+ # Private method that adds custom eager load paths to the ones defined by
130
+ # +paths+.
131
+ def all_eager_load_paths # :nodoc:
132
+ eager_load_paths + paths.eager_load
94
133
  end
95
134
  end
96
135
  end
data/lib/rails/engine.rb CHANGED
@@ -15,7 +15,8 @@ module Rails
15
15
  # feature and application sharing.
16
16
  #
17
17
  # Any +Rails::Engine+ is also a Rails::Railtie, so the same
18
- # methods (like <tt>rake_tasks</tt> and +generators+) and configuration
18
+ # methods (like {rake_tasks}[rdoc-ref:Rails::Railtie::rake_tasks] and
19
+ # {generators}[rdoc-ref:Rails::Railtie::generators]) and configuration
19
20
  # options that are available in railties can also be used in engines.
20
21
  #
21
22
  # == Creating an Engine
@@ -116,7 +117,7 @@ module Rails
116
117
  # An engine can also be a Rack application. It can be useful if you have a Rack application that
117
118
  # you would like to provide with some of the +Engine+'s features.
118
119
  #
119
- # To do that, use the +endpoint+ method:
120
+ # To do that, use the ::endpoint method:
120
121
  #
121
122
  # module MyEngine
122
123
  # class Engine < Rails::Engine
@@ -197,7 +198,7 @@ module Rails
197
198
  # named routes from the application will be available to your engine's controllers as well.
198
199
  #
199
200
  # However, sometimes you want to isolate your engine from the application, especially if your engine
200
- # has its own router. To do that, you simply need to call +isolate_namespace+. This method requires
201
+ # has its own router. To do that, you simply need to call ::isolate_namespace. This method requires
201
202
  # you to pass a module where all your controllers, helpers, and models should be nested to:
202
203
  #
203
204
  # module MyEngine
@@ -300,7 +301,7 @@ module Rails
300
301
  #
301
302
  # == Isolated engine's helpers
302
303
  #
303
- # Sometimes you may want to isolate engine, but use helpers that are defined for it.
304
+ # Sometimes you may want to isolate an engine, but use helpers that are defined for it.
304
305
  # If you want to share just a few specific helpers you can add them to application's
305
306
  # helpers in ApplicationController:
306
307
  #
@@ -327,7 +328,7 @@ module Rails
327
328
  # To use engine's migrations in application you can use the rake task below, which copies them to
328
329
  # application's dir:
329
330
  #
330
- # rake ENGINE_NAME:install:migrations
331
+ # $ rake ENGINE_NAME:install:migrations
331
332
  #
332
333
  # Note that some of the migrations may be skipped if a migration with the same name already exists
333
334
  # in application. In such a situation you must decide whether to leave that migration or rename the
@@ -395,6 +396,12 @@ module Rails
395
396
 
396
397
  unless mod.respond_to?(:table_name_prefix)
397
398
  define_method(:table_name_prefix) { "#{name}_" }
399
+
400
+ ActiveSupport.on_load(:active_record) do
401
+ mod.singleton_class.redefine_method(:table_name_prefix) do
402
+ "#{ActiveRecord::Base.table_name_prefix}#{name}_"
403
+ end
404
+ end
398
405
  end
399
406
 
400
407
  unless mod.respond_to?(:use_relative_model_naming?)
@@ -444,8 +451,7 @@ module Rails
444
451
  # Load console and invoke the registered hooks.
445
452
  # Check Rails::Railtie.console for more info.
446
453
  def load_console(app = self)
447
- require "rails/console/app"
448
- require "rails/console/helpers"
454
+ require "rails/console/methods"
449
455
  run_console_blocks(app)
450
456
  self
451
457
  end
@@ -578,7 +584,7 @@ module Rails
578
584
  end
579
585
 
580
586
  initializer :set_eager_load_paths, before: :bootstrap_hook do
581
- ActiveSupport::Dependencies._eager_load_paths.merge(config.eager_load_paths)
587
+ ActiveSupport::Dependencies._eager_load_paths.merge(config.all_eager_load_paths)
582
588
  config.eager_load_paths.freeze
583
589
  end
584
590
 
@@ -620,7 +626,7 @@ module Rails
620
626
  next if is_a?(Rails::Application)
621
627
 
622
628
  fixtures = config.root.join("test", "fixtures")
623
- if fixtures_in_root_and_not_in_vendor?(fixtures)
629
+ if fixtures_in_root_and_not_in_vendor_or_dot_dir?(fixtures)
624
630
  ActiveSupport.on_load(:active_record_fixtures) { self.fixture_paths |= ["#{fixtures}/"] }
625
631
  end
626
632
  end
@@ -637,9 +643,9 @@ module Rails
637
643
  end
638
644
  end
639
645
 
640
- initializer :wrap_executor_around_load_seed do |app|
646
+ initializer :wrap_reloader_around_load_seed do |app|
641
647
  self.class.set_callback(:load_seed, :around) do |engine, seeds_block|
642
- app.executor.wrap(&seeds_block)
648
+ app.reloader.wrap(&seeds_block)
643
649
  end
644
650
  end
645
651
 
@@ -705,14 +711,14 @@ module Rails
705
711
  end
706
712
 
707
713
  def _all_autoload_once_paths
708
- config.autoload_once_paths.uniq
714
+ config.all_autoload_once_paths.uniq
709
715
  end
710
716
 
711
717
  def _all_autoload_paths
712
718
  @_all_autoload_paths ||= begin
713
- autoload_paths = config.autoload_paths
714
- autoload_paths += config.eager_load_paths
715
- autoload_paths -= config.autoload_once_paths
719
+ autoload_paths = config.all_autoload_paths
720
+ autoload_paths += config.all_eager_load_paths
721
+ autoload_paths -= config.all_autoload_once_paths
716
722
  autoload_paths.uniq
717
723
  end
718
724
  end
@@ -728,9 +734,10 @@ module Rails
728
734
  end
729
735
  end
730
736
 
731
- def fixtures_in_root_and_not_in_vendor?(fixtures)
737
+ def fixtures_in_root_and_not_in_vendor_or_dot_dir?(fixtures)
732
738
  fixtures.exist? && fixtures.to_s.start_with?(Rails.root.to_s) &&
733
- !fixtures.to_s.start_with?(Rails.root.join("vendor").to_s)
739
+ !fixtures.to_s.start_with?(Rails.root.join("vendor").to_s) &&
740
+ !fixtures.to_s.start_with?("#{Rails.root}/.".to_s)
734
741
  end
735
742
 
736
743
  def build_request(env)
@@ -8,9 +8,9 @@ module Rails
8
8
 
9
9
  module VERSION
10
10
  MAJOR = 7
11
- MINOR = 1
12
- TINY = 0
13
- PRE = nil
11
+ MINOR = 2
12
+ TINY = 2
13
+ PRE = "1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -32,21 +32,27 @@ module Rails
32
32
  @name = name
33
33
  end
34
34
 
35
- # GET index
35
+ # Used for:
36
+ #
37
+ # * GET +index+
36
38
  def self.all(klass)
37
39
  "#{klass}.all"
38
40
  end
39
41
 
40
- # GET show
41
- # GET edit
42
- # PATCH/PUT update
43
- # DELETE destroy
42
+ # Used for:
43
+ #
44
+ # * GET +show+
45
+ # * GET +edit+
46
+ # * PATCH / PUT +update+
47
+ # * DELETE +destroy+
44
48
  def self.find(klass, params = nil)
45
49
  "#{klass}.find(#{params})"
46
50
  end
47
51
 
48
- # GET new
49
- # POST create
52
+ # Used for:
53
+ #
54
+ # * GET +new+
55
+ # * POST +create+
50
56
  def self.build(klass, params = nil)
51
57
  if params
52
58
  "#{klass}.new(#{params})"
@@ -55,23 +61,31 @@ module Rails
55
61
  end
56
62
  end
57
63
 
58
- # POST create
64
+ # Used for:
65
+ #
66
+ # * POST +create+
59
67
  def save
60
68
  "#{name}.save"
61
69
  end
62
70
 
63
- # PATCH/PUT update
71
+ # Used for:
72
+ #
73
+ # * PATCH / PUT +update+
64
74
  def update(params = nil)
65
75
  "#{name}.update(#{params})"
66
76
  end
67
77
 
68
- # POST create
69
- # PATCH/PUT update
78
+ # Used for:
79
+ #
80
+ # * POST +create+
81
+ # * PATCH / PUT +update+
70
82
  def errors
71
83
  "#{name}.errors"
72
84
  end
73
85
 
74
- # DELETE destroy
86
+ # Used for:
87
+ #
88
+ # * DELETE +destroy+
75
89
  def destroy
76
90
  "#{name}.destroy!"
77
91
  end
@@ -12,12 +12,15 @@ require "active_support/core_ext/array/extract_options"
12
12
  module Rails
13
13
  module Generators
14
14
  class AppBase < Base # :nodoc:
15
- include Database
16
15
  include AppName
17
16
 
18
- NODE_LTS_VERSION = "18.15.0"
17
+ NODE_LTS_VERSION = "20.11.1"
19
18
  BUN_VERSION = "1.0.1"
20
19
 
20
+ JAVASCRIPT_OPTIONS = %w( importmap bun webpack esbuild rollup )
21
+ CSS_OPTIONS = %w( tailwind bootstrap bulma postcss sass )
22
+ ASSET_PIPELINE_OPTIONS = %w( none sprockets propshaft )
23
+
21
24
  attr_accessor :rails_template
22
25
  add_shebang_option!
23
26
 
@@ -35,7 +38,8 @@ module Rails
35
38
  desc: "Path to some #{name} template (can be a filesystem path or URL)"
36
39
 
37
40
  class_option :database, type: :string, aliases: "-d", default: "sqlite3",
38
- desc: "Preconfigure for selected database (options: #{DATABASES.join('/')})"
41
+ enum: Database::DATABASES,
42
+ desc: "Preconfigure for selected database"
39
43
 
40
44
  class_option :skip_git, type: :boolean, aliases: "-G", default: nil,
41
45
  desc: "Skip git init, .gitignore and .gitattributes"
@@ -71,7 +75,8 @@ module Rails
71
75
  class_option :skip_asset_pipeline, type: :boolean, aliases: "-A", default: nil
72
76
 
73
77
  class_option :asset_pipeline, type: :string, aliases: "-a", default: "sprockets",
74
- desc: "Choose your asset pipeline [options: sprockets (default), propshaft]"
78
+ enum: ASSET_PIPELINE_OPTIONS,
79
+ desc: "Choose your asset pipeline"
75
80
 
76
81
  class_option :skip_javascript, type: :boolean, aliases: ["-J", "--skip-js"], default: (true if name == "plugin"),
77
82
  desc: "Skip JavaScript files"
@@ -94,9 +99,21 @@ module Rails
94
99
  class_option :skip_dev_gems, type: :boolean, default: nil,
95
100
  desc: "Skip development gems (e.g., web-console)"
96
101
 
102
+ class_option :skip_rubocop, type: :boolean, default: nil,
103
+ desc: "Skip RuboCop setup"
104
+
105
+ class_option :skip_brakeman, type: :boolean, default: nil,
106
+ desc: "Skip brakeman setup"
107
+
108
+ class_option :skip_ci, type: :boolean, default: nil,
109
+ desc: "Skip GitHub CI files"
110
+
97
111
  class_option :dev, type: :boolean, default: nil,
98
112
  desc: "Set up the #{name} with Gemfile pointing to your Rails checkout"
99
113
 
114
+ class_option :devcontainer, type: :boolean, default: false,
115
+ desc: "Generate devcontainer files"
116
+
100
117
  class_option :edge, type: :boolean, default: nil,
101
118
  desc: "Set up the #{name} with a Gemfile pointing to the #{edge_branch} branch on the Rails repository"
102
119
 
@@ -260,7 +277,7 @@ module Rails
260
277
  def database_gemfile_entry # :doc:
261
278
  return if options[:skip_active_record]
262
279
 
263
- gem_name, gem_version = gem_for_database
280
+ gem_name, gem_version = database.gem
264
281
  GemfileEntry.version gem_name, gem_version,
265
282
  "Use #{options[:database]} as the database for Active Record"
266
283
  end
@@ -345,6 +362,10 @@ module Rails
345
362
  options[:skip_active_storage]
346
363
  end
347
364
 
365
+ def skip_storage? # :doc:
366
+ skip_active_storage? && !sqlite3?
367
+ end
368
+
348
369
  def skip_action_cable? # :doc:
349
370
  options[:skip_action_cable]
350
371
  end
@@ -373,6 +394,25 @@ module Rails
373
394
  skip_asset_pipeline? || options[:asset_pipeline] != "propshaft"
374
395
  end
375
396
 
397
+ def skip_rubocop?
398
+ options[:skip_rubocop]
399
+ end
400
+
401
+ def skip_brakeman?
402
+ options[:skip_brakeman]
403
+ end
404
+
405
+ def skip_ci?
406
+ options[:skip_ci]
407
+ end
408
+
409
+ def skip_devcontainer?
410
+ !options[:devcontainer]
411
+ end
412
+
413
+ def devcontainer?
414
+ options[:devcontainer]
415
+ end
376
416
 
377
417
  class GemfileEntry < Struct.new(:name, :version, :comment, :options, :commented_out)
378
418
  def initialize(name, version, comment, options = {}, commented_out = false)
@@ -410,10 +450,6 @@ module Rails
410
450
  end
411
451
  end
412
452
 
413
- def gem_ruby_version
414
- Gem::Version.new(Gem::VERSION) >= Gem::Version.new("3.3.13") ? Gem.ruby_version : RUBY_VERSION
415
- end
416
-
417
453
  def rails_prerelease?
418
454
  options.dev? || options.edge? || options.main?
419
455
  end
@@ -535,17 +571,28 @@ module Rails
535
571
  binfixups
536
572
  end
537
573
 
538
- def dockerfile_build_packages
539
- # start with the essentials
540
- packages = %w(build-essential git pkg-config)
574
+ def dockerfile_base_packages
575
+ # Add curl to work with the default healthcheck strategy in Kamal
576
+ packages = ["curl"]
541
577
 
542
- # add database support
543
- packages << build_package_for_database unless skip_active_record?
578
+ # ActiveRecord databases
579
+ packages << database.base_package unless skip_active_record?
544
580
 
545
581
  # ActiveStorage preview support
546
582
  packages << "libvips" unless skip_active_storage?
547
583
 
548
- packages << "curl" if using_js_runtime?
584
+ # jemalloc for memory optimization
585
+ packages << "libjemalloc2"
586
+
587
+ packages.compact.sort
588
+ end
589
+
590
+ def dockerfile_build_packages
591
+ # start with the essentials
592
+ packages = %w(build-essential git pkg-config)
593
+
594
+ # add database support
595
+ packages << database.build_package unless skip_active_record?
549
596
 
550
597
  packages << "unzip" if using_bun?
551
598
 
@@ -553,43 +600,14 @@ module Rails
553
600
  if using_node?
554
601
  packages << "node-gyp" # pkg-config already listed above
555
602
 
556
- # module build process depends on Python, and debian changed
557
- # how python is installed with the bullseye release. Below
558
- # is based on debian release included with the Ruby images on
559
- # Dockerhub.
560
- case Gem.ruby_version.to_s
561
- when /^2\.7/
562
- bullseye = Gem.ruby_version >= Gem::Version.new("2.7.4")
563
- when /^3\.0/
564
- bullseye = Gem.ruby_version >= Gem::Version.new("3.0.2")
565
- else
566
- bullseye = true
567
- end
568
-
569
- if bullseye
570
- packages << "python-is-python3"
571
- else
572
- packages << "python"
573
- end
603
+ packages << "python-is-python3"
574
604
  end
575
605
 
576
606
  packages.compact.sort
577
607
  end
578
608
 
579
- def dockerfile_deploy_packages
580
- # Add curl to work with the default healthcheck strategy in Kamal
581
- packages = ["curl"]
582
-
583
- # ActiveRecord databases
584
- packages << deploy_package_for_database unless skip_active_record?
585
-
586
- # ActiveStorage preview support
587
- packages << "libvips" unless skip_active_storage?
588
-
589
- packages.compact.sort
590
- end
591
-
592
609
  def css_gemfile_entry
610
+ return if options[:api]
593
611
  return unless options[:css]
594
612
 
595
613
  if !using_js_runtime? && options[:css] == "tailwind"
@@ -656,7 +674,6 @@ module Rails
656
674
  if !File.exist?(File.expand_path("Gemfile", destination_root))
657
675
  create_file("Gemfile", <<~GEMFILE)
658
676
  source "https://rubygems.org"
659
- git_source(:github) { |repo| "https://github.com/\#{repo}.git" }
660
677
  #{rails_gemfile_entry}
661
678
  GEMFILE
662
679
 
@@ -674,19 +691,7 @@ module Rails
674
691
  end
675
692
 
676
693
  def run_bundle
677
- if bundle_install?
678
- bundle_command("install", "BUNDLE_IGNORE_MESSAGES" => "1")
679
-
680
- # The vast majority of Rails apps will be deployed on `x86_64-linux`.
681
- platforms = ["--add-platform=x86_64-linux"]
682
-
683
- # Users that develop on M1 mac may use docker and would need `aarch64-linux` as well.
684
- platforms << "--add-platform=aarch64-linux" if RUBY_PLATFORM.start_with?("arm64")
685
-
686
- platforms.each do |platform|
687
- bundle_command("lock #{platform}", "BUNDLE_IGNORE_MESSAGES" => "1")
688
- end
689
- end
694
+ bundle_command("install --quiet", "BUNDLE_IGNORE_MESSAGES" => "1") if bundle_install?
690
695
  end
691
696
 
692
697
  def run_javascript
@@ -716,6 +721,16 @@ module Rails
716
721
  end
717
722
  end
718
723
 
724
+ def add_bundler_platforms
725
+ if bundle_install?
726
+ # The vast majority of Rails apps will be deployed on `x86_64-linux`.
727
+ bundle_command("lock --add-platform=x86_64-linux")
728
+
729
+ # Users that develop on M1 mac may use docker and would need `aarch64-linux` as well.
730
+ bundle_command("lock --add-platform=aarch64-linux") if RUBY_PLATFORM.start_with?("arm64")
731
+ end
732
+ end
733
+
719
734
  def generate_bundler_binstub
720
735
  if bundle_install?
721
736
  bundle_command("binstubs bundler")
@@ -754,11 +769,15 @@ module Rails
754
769
  def dockerfile_chown_directories
755
770
  directories = %w(log tmp)
756
771
 
757
- directories << "storage" unless skip_active_storage? && !sqlite3?
772
+ directories << "storage" unless skip_storage?
758
773
  directories << "db" unless skip_active_record?
759
774
 
760
775
  directories.sort
761
776
  end
777
+
778
+ def database
779
+ @database ||= Database.build(options[:database])
780
+ end
762
781
  end
763
782
  end
764
783
  end
@@ -79,7 +79,7 @@ module Rails
79
79
  #
80
80
  # For example, if the user invoke the controller generator as:
81
81
  #
82
- # bin/rails generate controller Account --test-framework=test_unit
82
+ # $ bin/rails generate controller Account --test-framework=test_unit
83
83
  #
84
84
  # The controller generator will then try to invoke the following generators:
85
85
  #
@@ -134,11 +134,11 @@ module Rails
134
134
  # All hooks come with switches for user interface. If you do not want
135
135
  # to use any test framework, you can do:
136
136
  #
137
- # bin/rails generate controller Account --skip-test-framework
137
+ # $ bin/rails generate controller Account --skip-test-framework
138
138
  #
139
139
  # Or similarly:
140
140
  #
141
- # bin/rails generate controller Account --no-test-framework
141
+ # $ bin/rails generate controller Account --no-test-framework
142
142
  #
143
143
  # ==== Boolean hooks
144
144
  #
@@ -150,7 +150,7 @@ module Rails
150
150
  #
151
151
  # Then, if you want webrat to be invoked, just supply:
152
152
  #
153
- # bin/rails generate controller Account --webrat
153
+ # $ bin/rails generate controller Account --webrat
154
154
  #
155
155
  # The hooks lookup is similar as above:
156
156
  #
@@ -222,7 +222,7 @@ module Rails
222
222
  end
223
223
 
224
224
  # Returns the default source root for a given generator. This is used internally
225
- # by rails to set its generators source root. If you want to customize your source
225
+ # by Rails to set its generators source root. If you want to customize your source
226
226
  # root, you should use source_root.
227
227
  def self.default_source_root
228
228
  return unless base_name && generator_name
@@ -423,6 +423,10 @@ module Rails
423
423
  path = File.expand_path(File.join(base_name, generator_name), base_root)
424
424
  path if File.exist?(path)
425
425
  end
426
+
427
+ def gem_ruby_version
428
+ Gem::Version.new(Gem::VERSION) >= Gem::Version.new("3.3.13") ? Gem.ruby_version : RUBY_VERSION
429
+ end
426
430
  end
427
431
  end
428
432
  end