railties 7.1.3.4 → 8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +128 -775
  3. data/lib/minitest/rails_plugin.rb +6 -3
  4. data/lib/rails/all.rb +1 -3
  5. data/lib/rails/api/task.rb +6 -4
  6. data/lib/rails/application/bootstrap.rb +5 -7
  7. data/lib/rails/application/configuration.rb +81 -43
  8. data/lib/rails/application/default_middleware_stack.rb +4 -0
  9. data/lib/rails/application/dummy_config.rb +2 -2
  10. data/lib/rails/application/finisher.rb +9 -3
  11. data/lib/rails/application/routes_reloader.rb +16 -2
  12. data/lib/rails/application.rb +27 -86
  13. data/lib/rails/backtrace_cleaner.rb +19 -4
  14. data/lib/rails/cli.rb +0 -1
  15. data/lib/rails/code_statistics.rb +128 -86
  16. data/lib/rails/code_statistics_calculator.rb +78 -76
  17. data/lib/rails/command/helpers/editor.rb +1 -1
  18. data/lib/rails/command.rb +0 -6
  19. data/lib/rails/commands/app/update_command.rb +94 -0
  20. data/lib/rails/commands/boot/boot_command.rb +14 -0
  21. data/lib/rails/commands/console/console_command.rb +2 -21
  22. data/lib/rails/commands/console/irb_console.rb +128 -0
  23. data/lib/rails/commands/credentials/USAGE +4 -4
  24. data/lib/rails/commands/credentials/credentials_command.rb +7 -3
  25. data/lib/rails/commands/dbconsole/dbconsole_command.rb +21 -30
  26. data/lib/rails/commands/dev/dev_command.rb +1 -1
  27. data/lib/rails/commands/devcontainer/devcontainer_command.rb +40 -0
  28. data/lib/rails/commands/rake/rake_command.rb +1 -1
  29. data/lib/rails/commands/runner/runner_command.rb +14 -3
  30. data/lib/rails/commands/server/server_command.rb +5 -3
  31. data/lib/rails/commands/stats/stats_command.rb +19 -0
  32. data/lib/rails/commands/test/test_command.rb +2 -0
  33. data/lib/rails/configuration.rb +10 -1
  34. data/lib/rails/console/methods.rb +7 -0
  35. data/lib/rails/dev_caching.rb +2 -2
  36. data/lib/rails/engine/configuration.rb +3 -1
  37. data/lib/rails/engine/lazy_route_set.rb +114 -0
  38. data/lib/rails/engine.rb +16 -12
  39. data/lib/rails/gem_version.rb +4 -4
  40. data/lib/rails/generators/actions.rb +3 -3
  41. data/lib/rails/generators/app_base.rb +115 -68
  42. data/lib/rails/generators/base.rb +1 -1
  43. data/lib/rails/generators/database.rb +263 -71
  44. data/lib/rails/generators/erb/authentication/authentication_generator.rb +15 -0
  45. data/lib/rails/generators/erb/authentication/templates/app/views/passwords/edit.html.erb +9 -0
  46. data/lib/rails/generators/erb/authentication/templates/app/views/passwords/new.html.erb +8 -0
  47. data/lib/rails/generators/erb/authentication/templates/app/views/sessions/new.html.erb +11 -0
  48. data/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt +2 -0
  49. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +2 -0
  50. data/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt +2 -0
  51. data/lib/rails/generators/generated_attribute.rb +42 -12
  52. data/lib/rails/generators/migration.rb +3 -3
  53. data/lib/rails/generators/rails/app/app_generator.rb +75 -54
  54. data/lib/rails/generators/rails/app/templates/Dockerfile.tt +33 -17
  55. data/lib/rails/generators/rails/app/templates/Gemfile.tt +38 -23
  56. data/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css.tt +6 -11
  57. data/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt +4 -0
  58. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +17 -3
  59. data/lib/rails/generators/rails/app/templates/app/views/pwa/manifest.json.erb.tt +22 -0
  60. data/lib/rails/generators/rails/app/templates/app/views/pwa/service-worker.js +26 -0
  61. data/lib/rails/generators/rails/app/templates/bin/brakeman.tt +6 -0
  62. data/lib/rails/generators/rails/app/templates/bin/dev.tt +1 -0
  63. data/lib/rails/generators/rails/app/templates/bin/rubocop.tt +7 -0
  64. data/lib/rails/generators/rails/app/templates/bin/setup.tt +6 -5
  65. data/lib/rails/generators/rails/app/templates/bin/thrust.tt +4 -0
  66. data/lib/rails/generators/rails/app/templates/config/application.rb.tt +1 -1
  67. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +26 -3
  68. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +30 -0
  69. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +47 -0
  70. data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +26 -3
  71. data/lib/rails/generators/rails/app/templates/config/deploy.yml.tt +128 -0
  72. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +22 -26
  73. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +36 -48
  74. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +7 -18
  75. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +0 -7
  76. data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +1 -1
  77. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_0.rb.tt +30 -0
  78. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +35 -27
  79. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +6 -0
  80. data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +7 -1
  81. data/lib/rails/generators/rails/app/templates/dockerignore.tt +20 -2
  82. data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +144 -0
  83. data/lib/rails/generators/rails/app/templates/github/dependabot.yml +12 -0
  84. data/lib/rails/generators/rails/app/templates/gitignore.tt +4 -5
  85. data/lib/rails/generators/rails/app/templates/kamal-secrets.tt +17 -0
  86. data/lib/rails/generators/rails/app/templates/public/400.html +114 -0
  87. data/lib/rails/generators/rails/app/templates/public/404.html +113 -66
  88. data/lib/rails/generators/rails/app/templates/public/406-unsupported-browser.html +114 -0
  89. data/lib/rails/generators/rails/app/templates/public/422.html +113 -66
  90. data/lib/rails/generators/rails/app/templates/public/500.html +113 -65
  91. data/lib/rails/generators/rails/app/templates/public/icon.png +0 -0
  92. data/lib/rails/generators/rails/app/templates/public/icon.svg +3 -0
  93. data/lib/rails/generators/rails/app/templates/rubocop.yml.tt +8 -0
  94. data/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt +1 -1
  95. data/lib/rails/generators/rails/authentication/USAGE +6 -0
  96. data/lib/rails/generators/rails/authentication/authentication_generator.rb +58 -0
  97. data/lib/rails/generators/rails/authentication/templates/app/channels/application_cable/connection.rb.tt +16 -0
  98. data/lib/rails/generators/rails/authentication/templates/app/controllers/concerns/authentication.rb.tt +52 -0
  99. data/lib/rails/generators/rails/authentication/templates/app/controllers/passwords_controller.rb.tt +33 -0
  100. data/lib/rails/generators/rails/authentication/templates/app/controllers/sessions_controller.rb.tt +21 -0
  101. data/lib/rails/generators/rails/authentication/templates/app/mailers/passwords_mailer.rb.tt +6 -0
  102. data/lib/rails/generators/rails/authentication/templates/app/models/current.rb.tt +4 -0
  103. data/lib/rails/generators/rails/authentication/templates/app/models/session.rb.tt +3 -0
  104. data/lib/rails/generators/rails/authentication/templates/app/models/user.rb.tt +6 -0
  105. data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.html.erb.tt +4 -0
  106. data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.text.erb.tt +2 -0
  107. data/lib/rails/generators/rails/authentication/templates/test/mailers/previews/passwords_mailer_preview.rb.tt +7 -0
  108. data/lib/rails/generators/rails/controller/controller_generator.rb +1 -1
  109. data/lib/rails/generators/rails/credentials/templates/credentials.yml.tt +4 -0
  110. data/lib/rails/generators/rails/db/system/change/change_generator.rb +132 -21
  111. data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +176 -0
  112. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/Dockerfile.tt +3 -0
  113. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/compose.yaml.tt +47 -0
  114. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +37 -0
  115. data/lib/rails/generators/rails/migration/migration_generator.rb +4 -0
  116. data/lib/rails/generators/rails/plugin/plugin_generator.rb +47 -16
  117. data/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt +2 -2
  118. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +6 -2
  119. data/lib/rails/generators/rails/plugin/templates/app/views/layouts/%namespaced_name%/application.html.erb.tt +2 -0
  120. data/lib/rails/generators/rails/plugin/templates/bin/rubocop.tt +7 -0
  121. data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +103 -0
  122. data/lib/rails/generators/rails/plugin/templates/github/dependabot.yml +12 -0
  123. data/lib/rails/generators/rails/plugin/templates/rubocop.yml.tt +8 -0
  124. data/lib/rails/generators/rails/plugin/templates/test/application_system_test_case.rb.tt +1 -1
  125. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +2 -2
  126. data/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt +2 -2
  127. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt +3 -3
  128. data/lib/rails/generators/rails/script/USAGE +18 -0
  129. data/lib/rails/generators/rails/script/script_generator.rb +18 -0
  130. data/lib/rails/generators/rails/script/templates/script.rb.tt +3 -0
  131. data/lib/rails/generators/test_unit/authentication/authentication_generator.rb +14 -0
  132. data/lib/rails/generators/test_unit/authentication/templates/test/fixtures/users.yml.tt +9 -0
  133. data/lib/rails/generators/test_unit/authentication/templates/test/models/user_test.rb.tt +7 -0
  134. data/lib/rails/generators/test_unit/mailer/templates/functional_test.rb.tt +6 -4
  135. data/lib/rails/generators/test_unit/mailer/templates/preview.rb.tt +3 -2
  136. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +15 -1
  137. data/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt +2 -2
  138. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt +2 -2
  139. data/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt +2 -0
  140. data/lib/rails/generators/test_unit/system/templates/application_system_test_case.rb.tt +1 -1
  141. data/lib/rails/generators/testing/assertions.rb +20 -0
  142. data/lib/rails/generators/testing/behavior.rb +7 -6
  143. data/lib/rails/generators.rb +7 -2
  144. data/lib/rails/health_controller.rb +1 -1
  145. data/lib/rails/info.rb +2 -2
  146. data/lib/rails/info_controller.rb +10 -2
  147. data/lib/rails/mailers_controller.rb +14 -1
  148. data/lib/rails/paths.rb +2 -2
  149. data/lib/rails/pwa_controller.rb +15 -0
  150. data/lib/rails/rack/logger.rb +15 -7
  151. data/lib/rails/rack/silence_request.rb +33 -0
  152. data/lib/rails/rack.rb +1 -0
  153. data/lib/rails/railtie/configurable.rb +2 -2
  154. data/lib/rails/railtie.rb +15 -16
  155. data/lib/rails/source_annotation_extractor.rb +31 -14
  156. data/lib/rails/tasks/framework.rake +0 -26
  157. data/lib/rails/tasks/statistics.rake +13 -28
  158. data/lib/rails/tasks/tmp.rake +1 -1
  159. data/lib/rails/templates/layouts/application.html.erb +1 -1
  160. data/lib/rails/templates/rails/info/notes.html.erb +65 -0
  161. data/lib/rails/templates/rails/mailers/email.html.erb +12 -8
  162. data/lib/rails/templates/rails/welcome/index.html.erb +4 -2
  163. data/lib/rails/test_help.rb +2 -4
  164. data/lib/rails/test_unit/reporter.rb +8 -2
  165. data/lib/rails/test_unit/runner.rb +27 -2
  166. data/lib/rails/test_unit/test_parser.rb +48 -0
  167. data/lib/rails.rb +7 -4
  168. metadata +77 -45
  169. data/lib/rails/app_updater.rb +0 -40
  170. data/lib/rails/commands/secrets/USAGE +0 -61
  171. data/lib/rails/commands/secrets/secrets_command.rb +0 -47
  172. data/lib/rails/console/app.rb +0 -35
  173. data/lib/rails/console/helpers.rb +0 -19
  174. data/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt +0 -2
  175. data/lib/rails/generators/rails/app/templates/app/channels/application_cable/channel.rb.tt +0 -4
  176. data/lib/rails/generators/rails/app/templates/app/channels/application_cable/connection.rb.tt +0 -4
  177. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +0 -68
  178. data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt +0 -54
  179. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +0 -70
  180. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +0 -24
  181. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +0 -62
  182. data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +0 -53
  183. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_1.rb.tt +0 -284
  184. data/lib/rails/generators/rails/app/templates/config/initializers/permissions_policy.rb.tt +0 -13
  185. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon-precomposed.png +0 -0
  186. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon.png +0 -0
  187. data/lib/rails/generators/rails/app/templates/public/favicon.ico +0 -0
  188. data/lib/rails/generators/rails/app/templates/test/channels/application_cable/connection_test.rb.tt +0 -13
  189. data/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js.tt +0 -10
  190. data/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js.tt +0 -6
  191. data/lib/rails/generators/rails/plugin/templates/rails/javascripts.js.tt +0 -17
  192. data/lib/rails/ruby_version_check.rb +0 -17
  193. data/lib/rails/secrets.rb +0 -110
data/lib/rails/engine.rb CHANGED
@@ -6,7 +6,6 @@ require "active_support/callbacks"
6
6
  require "active_support/core_ext/module/delegation"
7
7
  require "active_support/core_ext/object/try"
8
8
  require "pathname"
9
- require "thread"
10
9
 
11
10
  module Rails
12
11
  # +Rails::Engine+ allows you to wrap a specific \Rails application or subset of
@@ -246,7 +245,7 @@ module Rails
246
245
  # polymorphic_url(MyEngine::Article.new)
247
246
  # # => "articles_path" # not "my_engine_articles_path"
248
247
  #
249
- # form_for(MyEngine::Article.new) do
248
+ # form_with(model: MyEngine::Article.new) do
250
249
  # text_field :title # => <input type="text" name="article[title]" id="article_title" />
251
250
  # end
252
251
  #
@@ -295,7 +294,7 @@ module Rails
295
294
  # All you need to do is pass the helper as the first element in array with
296
295
  # attributes for URL:
297
296
  #
298
- # form_for([my_engine, @user])
297
+ # form_with(model: [my_engine, @user])
299
298
  #
300
299
  # This code will use <tt>my_engine.user_path(@user)</tt> to generate the proper route.
301
300
  #
@@ -349,6 +348,7 @@ module Rails
349
348
  # config.railties_order = [Blog::Engine, :main_app, :all]
350
349
  class Engine < Railtie
351
350
  autoload :Configuration, "rails/engine/configuration"
351
+ autoload :LazyRouteSet, "rails/engine/lazy_route_set"
352
352
 
353
353
  class << self
354
354
  attr_accessor :called_from, :isolated
@@ -385,7 +385,8 @@ module Rails
385
385
  def isolate_namespace(mod)
386
386
  engine_name(generate_railtie_name(mod.name))
387
387
 
388
- routes.default_scope = { module: ActiveSupport::Inflector.underscore(mod.name) }
388
+ config.default_scope = { module: ActiveSupport::Inflector.underscore(mod.name) }
389
+
389
390
  self.isolated = true
390
391
 
391
392
  unless mod.respond_to?(:railtie_namespace)
@@ -451,8 +452,6 @@ module Rails
451
452
  # Load console and invoke the registered hooks.
452
453
  # Check Rails::Railtie.console for more info.
453
454
  def load_console(app = self)
454
- require "rails/console/app"
455
- require "rails/console/helpers"
456
455
  run_console_blocks(app)
457
456
  self
458
457
  end
@@ -544,7 +543,7 @@ module Rails
544
543
  # Defines the routes for this engine. If a block is given to
545
544
  # routes, it is appended to the engine.
546
545
  def routes(&block)
547
- @routes ||= ActionDispatch::Routing::RouteSet.new_with_config(config)
546
+ @routes ||= config.route_set_class.new_with_config(config)
548
547
  @routes.append(&block) if block_given?
549
548
  @routes
550
549
  end
@@ -589,6 +588,10 @@ module Rails
589
588
  config.eager_load_paths.freeze
590
589
  end
591
590
 
591
+ initializer :make_routes_lazy, before: :bootstrap_hook do |app|
592
+ config.route_set_class = LazyRouteSet if Rails.env.local?
593
+ end
594
+
592
595
  initializer :add_routing_paths do |app|
593
596
  routing_paths = paths["config/routes.rb"].existent
594
597
  external_paths = self.paths["config/routes"].paths
@@ -627,7 +630,7 @@ module Rails
627
630
  next if is_a?(Rails::Application)
628
631
 
629
632
  fixtures = config.root.join("test", "fixtures")
630
- if fixtures_in_root_and_not_in_vendor?(fixtures)
633
+ if fixtures_in_root_and_not_in_vendor_or_dot_dir?(fixtures)
631
634
  ActiveSupport.on_load(:active_record_fixtures) { self.fixture_paths |= ["#{fixtures}/"] }
632
635
  end
633
636
  end
@@ -644,9 +647,9 @@ module Rails
644
647
  end
645
648
  end
646
649
 
647
- initializer :wrap_executor_around_load_seed do |app|
650
+ initializer :wrap_reloader_around_load_seed do |app|
648
651
  self.class.set_callback(:load_seed, :around) do |engine, seeds_block|
649
- app.executor.wrap(&seeds_block)
652
+ app.reloader.wrap(&seeds_block)
650
653
  end
651
654
  end
652
655
 
@@ -735,9 +738,10 @@ module Rails
735
738
  end
736
739
  end
737
740
 
738
- def fixtures_in_root_and_not_in_vendor?(fixtures)
741
+ def fixtures_in_root_and_not_in_vendor_or_dot_dir?(fixtures)
739
742
  fixtures.exist? && fixtures.to_s.start_with?(Rails.root.to_s) &&
740
- !fixtures.to_s.start_with?(Rails.root.join("vendor").to_s)
743
+ !fixtures.to_s.start_with?(Rails.root.join("vendor").to_s) &&
744
+ !fixtures.to_s.start_with?("#{Rails.root}/.".to_s)
741
745
  end
742
746
 
743
747
  def build_request(env)
@@ -7,10 +7,10 @@ module Rails
7
7
  end
8
8
 
9
9
  module VERSION
10
- MAJOR = 7
11
- MINOR = 1
12
- TINY = 3
13
- PRE = "4"
10
+ MAJOR = 8
11
+ MINOR = 0
12
+ TINY = 1
13
+ PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -516,9 +516,9 @@ module Rails
516
516
 
517
517
  def route_namespace_pattern(namespace)
518
518
  namespace.each_with_index.reverse_each.reduce(nil) do |pattern, (name, i)|
519
- cummulative_margin = "\\#{i + 1}[ ]{2}"
520
- blank_or_indented_line = "^[ ]*\n|^#{cummulative_margin}.*\n"
521
- "(?:(?:#{blank_or_indented_line})*?^(#{cummulative_margin})namespace :#{name} do\n#{pattern})?"
519
+ cumulative_margin = "\\#{i + 1}[ ]{2}"
520
+ blank_or_indented_line = "^[ ]*\n|^#{cumulative_margin}.*\n"
521
+ "(?:(?:#{blank_or_indented_line})*?^(#{cumulative_margin})namespace :#{name} do\n#{pattern})?"
522
522
  end.then do |pattern|
523
523
  /^([ ]*).+\.routes\.draw do[ ]*\n#{pattern}/
524
524
  end
@@ -12,12 +12,14 @@ 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
+
21
23
  attr_accessor :rails_template
22
24
  add_shebang_option!
23
25
 
@@ -35,7 +37,8 @@ module Rails
35
37
  desc: "Path to some #{name} template (can be a filesystem path or URL)"
36
38
 
37
39
  class_option :database, type: :string, aliases: "-d", default: "sqlite3",
38
- desc: "Preconfigure for selected database (options: #{DATABASES.join('/')})"
40
+ enum: Database::DATABASES,
41
+ desc: "Preconfigure for selected database"
39
42
 
40
43
  class_option :skip_git, type: :boolean, aliases: "-G", default: nil,
41
44
  desc: "Skip git init, .gitignore and .gitattributes"
@@ -70,9 +73,6 @@ module Rails
70
73
 
71
74
  class_option :skip_asset_pipeline, type: :boolean, aliases: "-A", default: nil
72
75
 
73
- class_option :asset_pipeline, type: :string, aliases: "-a", default: "sprockets",
74
- desc: "Choose your asset pipeline [options: sprockets (default), propshaft]"
75
-
76
76
  class_option :skip_javascript, type: :boolean, aliases: ["-J", "--skip-js"], default: (true if name == "plugin"),
77
77
  desc: "Skip JavaScript files"
78
78
 
@@ -94,9 +94,30 @@ module Rails
94
94
  class_option :skip_dev_gems, type: :boolean, default: nil,
95
95
  desc: "Skip development gems (e.g., web-console)"
96
96
 
97
+ class_option :skip_thruster, type: :boolean, default: nil,
98
+ desc: "Skip Thruster setup"
99
+
100
+ class_option :skip_rubocop, type: :boolean, default: nil,
101
+ desc: "Skip RuboCop setup"
102
+
103
+ class_option :skip_brakeman, type: :boolean, default: nil,
104
+ desc: "Skip brakeman setup"
105
+
106
+ class_option :skip_ci, type: :boolean, default: nil,
107
+ desc: "Skip GitHub CI files"
108
+
109
+ class_option :skip_kamal, type: :boolean, default: nil,
110
+ desc: "Skip Kamal setup"
111
+
112
+ class_option :skip_solid, type: :boolean, default: nil,
113
+ desc: "Skip Solid Cache, Queue, and Cable setup"
114
+
97
115
  class_option :dev, type: :boolean, default: nil,
98
116
  desc: "Set up the #{name} with Gemfile pointing to your Rails checkout"
99
117
 
118
+ class_option :devcontainer, type: :boolean, default: nil,
119
+ desc: "Generate devcontainer files"
120
+
100
121
  class_option :edge, type: :boolean, default: nil,
101
122
  desc: "Set up the #{name} with a Gemfile pointing to the #{edge_branch} branch on the Rails repository"
102
123
 
@@ -180,7 +201,7 @@ module Rails
180
201
 
181
202
  OPTION_IMPLICATIONS = { # :nodoc:
182
203
  skip_active_job: [:skip_action_mailer, :skip_active_storage],
183
- skip_active_record: [:skip_active_storage],
204
+ skip_active_record: [:skip_active_storage, :skip_solid],
184
205
  skip_active_storage: [:skip_action_mailbox, :skip_action_text],
185
206
  skip_javascript: [:skip_hotwire],
186
207
  }
@@ -260,7 +281,7 @@ module Rails
260
281
  def database_gemfile_entry # :doc:
261
282
  return if options[:skip_active_record]
262
283
 
263
- gem_name, gem_version = gem_for_database
284
+ gem_name, gem_version = database.gem
264
285
  GemfileEntry.version gem_name, gem_version,
265
286
  "Use #{options[:database]} as the database for Active Record"
266
287
  end
@@ -270,12 +291,7 @@ module Rails
270
291
  end
271
292
 
272
293
  def asset_pipeline_gemfile_entry
273
- return if skip_asset_pipeline?
274
-
275
- if options[:asset_pipeline] == "sprockets"
276
- GemfileEntry.floats "sprockets-rails",
277
- "The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]"
278
- elsif options[:asset_pipeline] == "propshaft"
294
+ unless skip_asset_pipeline?
279
295
  GemfileEntry.floats "propshaft", "The modern asset pipeline for Rails [https://github.com/rails/propshaft]"
280
296
  end
281
297
  end
@@ -345,6 +361,10 @@ module Rails
345
361
  options[:skip_active_storage]
346
362
  end
347
363
 
364
+ def skip_storage? # :doc:
365
+ skip_active_storage? && !sqlite3?
366
+ end
367
+
348
368
  def skip_action_cable? # :doc:
349
369
  options[:skip_action_cable]
350
370
  end
@@ -365,14 +385,37 @@ module Rails
365
385
  options[:skip_asset_pipeline]
366
386
  end
367
387
 
368
- def skip_sprockets?
369
- skip_asset_pipeline? || options[:asset_pipeline] != "sprockets"
388
+ def skip_thruster?
389
+ options[:skip_thruster]
370
390
  end
371
391
 
372
- def skip_propshaft?
373
- skip_asset_pipeline? || options[:asset_pipeline] != "propshaft"
392
+ def skip_rubocop?
393
+ options[:skip_rubocop]
374
394
  end
375
395
 
396
+ def skip_brakeman?
397
+ options[:skip_brakeman]
398
+ end
399
+
400
+ def skip_ci?
401
+ options[:skip_ci]
402
+ end
403
+
404
+ def skip_devcontainer?
405
+ !options[:devcontainer]
406
+ end
407
+
408
+ def devcontainer?
409
+ options[:devcontainer]
410
+ end
411
+
412
+ def skip_kamal?
413
+ options[:skip_kamal]
414
+ end
415
+
416
+ def skip_solid?
417
+ options[:skip_solid]
418
+ end
376
419
 
377
420
  class GemfileEntry < Struct.new(:name, :version, :comment, :options, :commented_out)
378
421
  def initialize(name, version, comment, options = {}, commented_out = false)
@@ -410,10 +453,6 @@ module Rails
410
453
  end
411
454
  end
412
455
 
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
456
  def rails_prerelease?
418
457
  options.dev? || options.edge? || options.main?
419
458
  end
@@ -535,17 +574,28 @@ module Rails
535
574
  binfixups
536
575
  end
537
576
 
538
- def dockerfile_build_packages
539
- # start with the essentials
540
- packages = %w(build-essential git pkg-config)
577
+ def dockerfile_base_packages
578
+ # Add curl to work with the default health check strategy in Kamal
579
+ packages = ["curl"]
541
580
 
542
- # add database support
543
- packages << build_package_for_database unless skip_active_record?
581
+ # ActiveRecord databases
582
+ packages << database.base_package unless skip_active_record?
544
583
 
545
584
  # ActiveStorage preview support
546
585
  packages << "libvips" unless skip_active_storage?
547
586
 
548
- packages << "curl" if using_js_runtime?
587
+ # jemalloc for memory optimization
588
+ packages << "libjemalloc2"
589
+
590
+ packages.compact.sort
591
+ end
592
+
593
+ def dockerfile_build_packages
594
+ # start with the essentials
595
+ packages = %w(build-essential git pkg-config)
596
+
597
+ # add database support
598
+ packages << database.build_package unless skip_active_record?
549
599
 
550
600
  packages << "unzip" if using_bun?
551
601
 
@@ -553,43 +603,22 @@ module Rails
553
603
  if using_node?
554
604
  packages << "node-gyp" # pkg-config already listed above
555
605
 
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
606
+ packages << "python-is-python3"
574
607
  end
575
608
 
576
609
  packages.compact.sort
577
610
  end
578
611
 
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
612
+ def ci_packages
613
+ if depends_on_system_test?
614
+ dockerfile_build_packages << "google-chrome-stable"
615
+ else
616
+ dockerfile_build_packages
617
+ end
590
618
  end
591
619
 
592
620
  def css_gemfile_entry
621
+ return if options[:api]
593
622
  return unless options[:css]
594
623
 
595
624
  if !using_js_runtime? && options[:css] == "tailwind"
@@ -602,10 +631,10 @@ module Rails
602
631
  end
603
632
 
604
633
  def cable_gemfile_entry
605
- return if options[:skip_action_cable]
606
-
607
- comment = "Use Redis adapter to run Action Cable in production"
608
- GemfileEntry.new("redis", ">= 4.0.1", comment, {}, true)
634
+ if !options[:skip_action_cable] && options[:skip_solid]
635
+ comment = "Use Redis adapter to run Action Cable in production"
636
+ GemfileEntry.new("redis", ">= 4.0.1", comment, {}, true)
637
+ end
609
638
  end
610
639
 
611
640
  def bundle_command(command, env = {})
@@ -638,10 +667,6 @@ module Rails
638
667
  !(options[:skip_bundle] || options[:pretend])
639
668
  end
640
669
 
641
- def bundler_windows_platforms
642
- Gem.rubygems_version >= Gem::Version.new("3.3.22") ? "windows" : "mswin mswin64 mingw x64_mingw"
643
- end
644
-
645
670
  def depends_on_system_test?
646
671
  !(options[:skip_system_test] || options[:skip_test] || options[:api])
647
672
  end
@@ -656,7 +681,6 @@ module Rails
656
681
  if !File.exist?(File.expand_path("Gemfile", destination_root))
657
682
  create_file("Gemfile", <<~GEMFILE)
658
683
  source "https://rubygems.org"
659
- git_source(:github) { |repo| "https://github.com/\#{repo}.git" }
660
684
  #{rails_gemfile_entry}
661
685
  GEMFILE
662
686
 
@@ -674,7 +698,7 @@ module Rails
674
698
  end
675
699
 
676
700
  def run_bundle
677
- bundle_command("install", "BUNDLE_IGNORE_MESSAGES" => "1") if bundle_install?
701
+ bundle_command("install --quiet", "BUNDLE_IGNORE_MESSAGES" => "1") if bundle_install?
678
702
  end
679
703
 
680
704
  def run_javascript
@@ -704,6 +728,25 @@ module Rails
704
728
  end
705
729
  end
706
730
 
731
+ def run_kamal
732
+ return if options[:skip_kamal] || !bundle_install?
733
+
734
+ bundle_command "binstubs kamal"
735
+ bundle_command "exec kamal init"
736
+
737
+ template "kamal-secrets.tt", ".kamal/secrets", force: true
738
+ template "config/deploy.yml", force: true
739
+ end
740
+
741
+ def run_solid
742
+ return if skip_solid? || !bundle_install?
743
+
744
+ commands = "solid_cache:install solid_queue:install"
745
+ commands += " solid_cable:install" unless skip_action_cable?
746
+
747
+ rails_command commands
748
+ end
749
+
707
750
  def add_bundler_platforms
708
751
  if bundle_install?
709
752
  # The vast majority of Rails apps will be deployed on `x86_64-linux`.
@@ -752,11 +795,15 @@ module Rails
752
795
  def dockerfile_chown_directories
753
796
  directories = %w(log tmp)
754
797
 
755
- directories << "storage" unless skip_active_storage? && !sqlite3?
798
+ directories << "storage" unless skip_storage?
756
799
  directories << "db" unless skip_active_record?
757
800
 
758
801
  directories.sort
759
802
  end
803
+
804
+ def database
805
+ @database ||= Database.build(options[:database])
806
+ end
760
807
  end
761
808
  end
762
809
  end
@@ -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