railties 7.2.3 → 8.0.5

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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +168 -256
  3. data/lib/minitest/rails_plugin.rb +8 -1
  4. data/lib/rails/application/bootstrap.rb +0 -1
  5. data/lib/rails/application/configuration.rb +17 -14
  6. data/lib/rails/application/default_middleware_stack.rb +4 -0
  7. data/lib/rails/application/finisher.rb +2 -3
  8. data/lib/rails/application/routes_reloader.rb +17 -3
  9. data/lib/rails/application.rb +10 -1
  10. data/lib/rails/application_controller.rb +2 -0
  11. data/lib/rails/backtrace_cleaner.rb +2 -2
  12. data/lib/rails/code_statistics.rb +128 -86
  13. data/lib/rails/code_statistics_calculator.rb +78 -76
  14. data/lib/rails/command/helpers/editor.rb +1 -1
  15. data/lib/rails/command.rb +0 -6
  16. data/lib/rails/commands/app/update_command.rb +5 -9
  17. data/lib/rails/commands/console/irb_console.rb +3 -6
  18. data/lib/rails/commands/credentials/USAGE +4 -4
  19. data/lib/rails/commands/credentials/credentials_command.rb +5 -1
  20. data/lib/rails/commands/dev/dev_command.rb +1 -1
  21. data/lib/rails/commands/devcontainer/devcontainer_command.rb +2 -1
  22. data/lib/rails/commands/stats/stats_command.rb +19 -0
  23. data/lib/rails/console/methods.rb +5 -21
  24. data/lib/rails/dev_caching.rb +2 -2
  25. data/lib/rails/engine/configuration.rb +3 -1
  26. data/lib/rails/engine/lazy_route_set.rb +111 -0
  27. data/lib/rails/engine.rb +10 -6
  28. data/lib/rails/gem_version.rb +3 -3
  29. data/lib/rails/generators/actions.rb +3 -3
  30. data/lib/rails/generators/app_base.rb +76 -56
  31. data/lib/rails/generators/base.rb +0 -4
  32. data/lib/rails/generators/bundle_helper.rb +34 -0
  33. data/lib/rails/generators/database.rb +101 -67
  34. data/lib/rails/generators/erb/authentication/authentication_generator.rb +15 -0
  35. data/lib/rails/generators/erb/authentication/templates/app/views/passwords/edit.html.erb +9 -0
  36. data/lib/rails/generators/erb/authentication/templates/app/views/passwords/new.html.erb +8 -0
  37. data/lib/rails/generators/erb/authentication/templates/app/views/sessions/new.html.erb +11 -0
  38. data/lib/rails/generators/generated_attribute.rb +16 -11
  39. data/lib/rails/generators/rails/app/app_generator.rb +30 -30
  40. data/lib/rails/generators/rails/app/templates/Dockerfile.tt +23 -6
  41. data/lib/rails/generators/rails/app/templates/Gemfile.tt +27 -12
  42. data/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css.tt +6 -11
  43. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +10 -3
  44. data/lib/rails/generators/rails/app/templates/bin/dev.tt +1 -0
  45. data/lib/rails/generators/rails/app/templates/bin/setup.tt +5 -8
  46. data/lib/rails/generators/rails/app/templates/bin/thrust.tt +4 -0
  47. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +24 -1
  48. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +23 -0
  49. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +50 -0
  50. data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +30 -5
  51. data/lib/rails/generators/rails/app/templates/config/deploy.yml.tt +128 -0
  52. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +12 -23
  53. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +31 -51
  54. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +5 -19
  55. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +0 -7
  56. data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +1 -1
  57. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_0.rb.tt +30 -0
  58. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +11 -2
  59. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +3 -3
  60. data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +4 -3
  61. data/lib/rails/generators/rails/app/templates/dockerignore.tt +7 -2
  62. data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +12 -6
  63. data/lib/rails/generators/rails/app/templates/gitignore.tt +1 -2
  64. data/lib/rails/generators/rails/app/templates/kamal-secrets.tt +17 -0
  65. data/lib/rails/generators/rails/app/templates/public/400.html +114 -0
  66. data/lib/rails/generators/rails/app/templates/public/404.html +113 -66
  67. data/lib/rails/generators/rails/app/templates/public/406-unsupported-browser.html +113 -65
  68. data/lib/rails/generators/rails/app/templates/public/422.html +113 -66
  69. data/lib/rails/generators/rails/app/templates/public/500.html +113 -65
  70. data/lib/rails/generators/rails/app/templates/public/icon.png +0 -0
  71. data/lib/rails/generators/rails/app/templates/public/icon.svg +2 -2
  72. data/lib/rails/generators/rails/app/templates/ruby-version.tt +1 -1
  73. data/lib/rails/generators/rails/authentication/USAGE +6 -0
  74. data/lib/rails/generators/rails/authentication/authentication_generator.rb +60 -0
  75. data/lib/rails/generators/rails/authentication/templates/app/channels/application_cable/connection.rb.tt +16 -0
  76. data/lib/rails/generators/rails/authentication/templates/app/controllers/concerns/authentication.rb.tt +52 -0
  77. data/lib/rails/generators/rails/authentication/templates/app/controllers/passwords_controller.rb.tt +33 -0
  78. data/lib/rails/generators/rails/authentication/templates/app/controllers/sessions_controller.rb.tt +21 -0
  79. data/lib/rails/generators/rails/authentication/templates/app/mailers/passwords_mailer.rb.tt +6 -0
  80. data/lib/rails/generators/rails/authentication/templates/app/models/current.rb.tt +4 -0
  81. data/lib/rails/generators/rails/authentication/templates/app/models/session.rb.tt +3 -0
  82. data/lib/rails/generators/rails/authentication/templates/app/models/user.rb.tt +6 -0
  83. data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.html.erb.tt +4 -0
  84. data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.text.erb.tt +2 -0
  85. data/lib/rails/generators/rails/credentials/templates/credentials.yml.tt +4 -0
  86. data/lib/rails/generators/rails/db/system/change/change_generator.rb +1 -1
  87. data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +12 -2
  88. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/Dockerfile.tt +1 -1
  89. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +5 -5
  90. data/lib/rails/generators/rails/plugin/plugin_generator.rb +7 -9
  91. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +1 -1
  92. data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +3 -3
  93. data/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt +2 -2
  94. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt +3 -3
  95. data/lib/rails/generators/rails/script/USAGE +18 -0
  96. data/lib/rails/generators/rails/script/script_generator.rb +18 -0
  97. data/lib/rails/generators/rails/script/templates/script.rb.tt +3 -0
  98. data/lib/rails/generators/test_unit/authentication/authentication_generator.rb +18 -0
  99. data/lib/rails/generators/test_unit/authentication/templates/test/fixtures/users.yml.tt +9 -0
  100. data/lib/rails/generators/test_unit/authentication/templates/test/mailers/previews/passwords_mailer_preview.rb.tt +7 -0
  101. data/lib/rails/generators/test_unit/authentication/templates/test/models/user_test.rb.tt +7 -0
  102. data/lib/rails/generators.rb +1 -0
  103. data/lib/rails/health_controller.rb +2 -0
  104. data/lib/rails/info.rb +2 -1
  105. data/lib/rails/info_controller.rb +10 -4
  106. data/lib/rails/rack/silence_request.rb +33 -0
  107. data/lib/rails/rack.rb +1 -0
  108. data/lib/rails/source_annotation_extractor.rb +37 -16
  109. data/lib/rails/tasks/statistics.rake +13 -28
  110. data/lib/rails/templates/rails/info/notes.html.erb +65 -0
  111. data/lib/rails/templates/rails/mailers/email.html.erb +1 -1
  112. data/lib/rails/test_unit/line_filtering.rb +24 -3
  113. data/lib/rails/test_unit/reporter.rb +8 -4
  114. data/lib/rails/test_unit/runner.rb +1 -0
  115. metadata +46 -37
  116. data/lib/rails/console/app.rb +0 -8
  117. data/lib/rails/console/helpers.rb +0 -8
  118. data/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt +0 -2
  119. data/lib/rails/generators/rails/app/templates/app/channels/application_cable/channel.rb.tt +0 -4
  120. data/lib/rails/generators/rails/app/templates/app/channels/application_cable/connection.rb.tt +0 -4
  121. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_2.rb.tt +0 -70
  122. data/lib/rails/generators/rails/app/templates/config/initializers/permissions_policy.rb.tt +0 -13
  123. data/lib/rails/generators/rails/app/templates/test/channels/application_cable/connection_test.rb.tt +0 -13
  124. data/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js.tt +0 -10
  125. data/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js.tt +0 -6
  126. data/lib/rails/generators/rails/plugin/templates/rails/javascripts.js.tt +0 -17
@@ -423,10 +423,6 @@ 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
430
426
  end
431
427
  end
432
428
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ module Generators
5
+ module BundleHelper # :nodoc:
6
+ def bundle_command(command, env = {}, params = {})
7
+ say_status :run, "bundle #{command}"
8
+
9
+ # We are going to shell out rather than invoking Bundler::CLI.new(command)
10
+ # because `rails new` loads the Thor gem and on the other hand bundler uses
11
+ # its own vendored Thor, which could be a different version. Running both
12
+ # things in the same process is a recipe for a night with paracetamol.
13
+ #
14
+ # Thanks to James Tucker for the Gem tricks involved in this call.
15
+ _bundle_command = Gem.bin_path("bundler", "bundle")
16
+
17
+ require "bundler"
18
+ Bundler.with_original_env do
19
+ exec_bundle_command(_bundle_command, command, env, params)
20
+ end
21
+ end
22
+
23
+ private
24
+ def exec_bundle_command(bundle_command, command, env, params)
25
+ full_command = %Q["#{Gem.ruby}" "#{bundle_command}" #{command}]
26
+ if options[:quiet] || params[:quiet]
27
+ system(env, full_command, out: File::NULL)
28
+ else
29
+ system(env, full_command)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -3,25 +3,91 @@
3
3
  module Rails
4
4
  module Generators
5
5
  class Database
6
- DATABASES = %w( mysql trilogy postgresql sqlite3 )
6
+ DATABASES = %w( mysql trilogy postgresql sqlite3 mariadb-mysql mariadb-trilogy )
7
+
8
+ module MySQL
9
+ def name
10
+ "mysql"
11
+ end
12
+
13
+ def port
14
+ 3306
15
+ end
16
+
17
+ def service
18
+ {
19
+ "image" => "mysql/mysql-server:8.0",
20
+ "restart" => "unless-stopped",
21
+ "environment" => {
22
+ "MYSQL_ALLOW_EMPTY_PASSWORD" => "true",
23
+ "MYSQL_ROOT_HOST" => "%"
24
+ },
25
+ "volumes" => ["mysql-data:/var/lib/mysql"],
26
+ "networks" => ["default"],
27
+ }
28
+ end
29
+
30
+ def socket
31
+ @socket ||= [
32
+ "/tmp/mysql.sock", # default
33
+ "/var/run/mysqld/mysqld.sock", # debian/gentoo
34
+ "/var/tmp/mysql.sock", # freebsd
35
+ "/var/lib/mysql/mysql.sock", # fedora
36
+ "/opt/local/lib/mysql/mysql.sock", # fedora
37
+ "/opt/local/var/run/mysqld/mysqld.sock", # mac + darwinports + mysql
38
+ "/opt/local/var/run/mysql4/mysqld.sock", # mac + darwinports + mysql4
39
+ "/opt/local/var/run/mysql5/mysqld.sock", # mac + darwinports + mysql5
40
+ "/opt/lampp/var/mysql/mysql.sock" # xampp for linux
41
+ ].find { |f| File.exist?(f) } unless Gem.win_platform?
42
+ end
43
+
44
+ def host
45
+ "127.0.0.1"
46
+ end
47
+ end
48
+
49
+ module MariaDB
50
+ def name
51
+ "mariadb"
52
+ end
53
+
54
+ def port
55
+ 3306
56
+ end
57
+
58
+ def service
59
+ {
60
+ "image" => "mariadb:10.5",
61
+ "restart" => "unless-stopped",
62
+ "networks" => ["default"],
63
+ "volumes" => ["mariadb-data:/var/lib/mysql"],
64
+ "environment" => {
65
+ "MARIADB_ALLOW_EMPTY_ROOT_PASSWORD" => "true",
66
+ },
67
+ }
68
+ end
69
+ end
7
70
 
8
71
  class << self
9
72
  def build(database_name)
10
73
  case database_name
11
- when "mysql" then MySQL.new
74
+ when "mysql" then MySQL2.new
12
75
  when "postgresql" then PostgreSQL.new
13
- when "trilogy" then MariaDB.new
76
+ when "trilogy" then Trilogy.new
14
77
  when "sqlite3" then SQLite3.new
78
+ when "mariadb-mysql" then MariaDBMySQL2.new
79
+ when "mariadb-trilogy" then MariaDBTrilogy.new
15
80
  else Null.new
16
81
  end
17
82
  end
18
83
 
19
84
  def all
20
85
  @all ||= [
21
- MySQL.new,
86
+ MySQL2.new,
22
87
  PostgreSQL.new,
23
- MariaDB.new,
24
88
  SQLite3.new,
89
+ MariaDBMySQL2.new,
90
+ MariaDBTrilogy.new
25
91
  ]
26
92
  end
27
93
  end
@@ -30,6 +96,10 @@ module Rails
30
96
  raise NotImplementedError
31
97
  end
32
98
 
99
+ def template
100
+ raise NotImplementedError
101
+ end
102
+
33
103
  def service
34
104
  raise NotImplementedError
35
105
  end
@@ -69,48 +139,11 @@ module Rails
69
139
  "#{name}-data"
70
140
  end
71
141
 
72
- module MySqlSocket
73
- def socket
74
- @socket ||= [
75
- "/tmp/mysql.sock", # default
76
- "/var/run/mysqld/mysqld.sock", # debian/gentoo
77
- "/var/tmp/mysql.sock", # freebsd
78
- "/var/lib/mysql/mysql.sock", # fedora
79
- "/opt/local/lib/mysql/mysql.sock", # fedora
80
- "/opt/local/var/run/mysqld/mysqld.sock", # mac + darwinports + mysql
81
- "/opt/local/var/run/mysql4/mysqld.sock", # mac + darwinports + mysql4
82
- "/opt/local/var/run/mysql5/mysqld.sock", # mac + darwinports + mysql5
83
- "/opt/lampp/var/mysql/mysql.sock" # xampp for linux
84
- ].find { |f| File.exist?(f) } unless Gem.win_platform?
85
- end
86
-
87
- def host
88
- "localhost"
89
- end
90
- end
91
-
92
- class MySQL < Database
93
- include MySqlSocket
142
+ class MySQL2 < Database
143
+ include MySQL
94
144
 
95
- def name
96
- "mysql"
97
- end
98
-
99
- def service
100
- {
101
- "image" => "mysql/mysql-server:8.0",
102
- "restart" => "unless-stopped",
103
- "environment" => {
104
- "MYSQL_ALLOW_EMPTY_PASSWORD" => "true",
105
- "MYSQL_ROOT_HOST" => "%"
106
- },
107
- "volumes" => ["mysql-data:/var/lib/mysql"],
108
- "networks" => ["default"],
109
- }
110
- end
111
-
112
- def port
113
- 3306
145
+ def template
146
+ "config/databases/mysql.yml"
114
147
  end
115
148
 
116
149
  def gem
@@ -135,6 +168,10 @@ module Rails
135
168
  "postgres"
136
169
  end
137
170
 
171
+ def template
172
+ "config/databases/postgresql.yml"
173
+ end
174
+
138
175
  def service
139
176
  {
140
177
  "image" => "postgres:16.1",
@@ -169,27 +206,11 @@ module Rails
169
206
  end
170
207
  end
171
208
 
172
- class MariaDB < Database
173
- include MySqlSocket
209
+ class Trilogy < Database
210
+ include MySQL
174
211
 
175
- def name
176
- "mariadb"
177
- end
178
-
179
- def service
180
- {
181
- "image" => "mariadb:10.5",
182
- "restart" => "unless-stopped",
183
- "networks" => ["default"],
184
- "volumes" => ["mariadb-data:/var/lib/mysql"],
185
- "environment" => {
186
- "MARIADB_ALLOW_EMPTY_ROOT_PASSWORD" => "true",
187
- },
188
- }
189
- end
190
-
191
- def port
192
- 3306
212
+ def template
213
+ "config/databases/trilogy.yml"
193
214
  end
194
215
 
195
216
  def gem
@@ -214,6 +235,10 @@ module Rails
214
235
  "sqlite3"
215
236
  end
216
237
 
238
+ def template
239
+ "config/databases/sqlite3.yml"
240
+ end
241
+
217
242
  def service
218
243
  nil
219
244
  end
@@ -223,7 +248,7 @@ module Rails
223
248
  end
224
249
 
225
250
  def gem
226
- ["sqlite3", [">= 1.4"]]
251
+ ["sqlite3", [">= 2.1"]]
227
252
  end
228
253
 
229
254
  def base_package
@@ -239,8 +264,17 @@ module Rails
239
264
  end
240
265
  end
241
266
 
267
+ class MariaDBMySQL2 < MySQL2
268
+ include MariaDB
269
+ end
270
+
271
+ class MariaDBTrilogy < Trilogy
272
+ include MariaDB
273
+ end
274
+
242
275
  class Null < Database
243
276
  def name; end
277
+ def template; end
244
278
  def service; end
245
279
  def port; end
246
280
  def volume; end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/erb"
4
+
5
+ module Erb # :nodoc:
6
+ module Generators # :nodoc:
7
+ class AuthenticationGenerator < Rails::Generators::Base # :nodoc:
8
+ def create_files
9
+ template "app/views/passwords/new.html.erb"
10
+ template "app/views/passwords/edit.html.erb"
11
+ template "app/views/sessions/new.html.erb"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ <h1>Update your password</h1>
2
+
3
+ <%%= tag.div(flash[:alert], style: "color:red") if flash[:alert] %>
4
+
5
+ <%%= form_with url: password_path(params[:token]), method: :put do |form| %>
6
+ <%%= form.password_field :password, required: true, autocomplete: "new-password", placeholder: "Enter new password", maxlength: 72 %><br>
7
+ <%%= form.password_field :password_confirmation, required: true, autocomplete: "new-password", placeholder: "Repeat new password", maxlength: 72 %><br>
8
+ <%%= form.submit "Save" %>
9
+ <%% end %>
@@ -0,0 +1,8 @@
1
+ <h1>Forgot your password?</h1>
2
+
3
+ <%%= tag.div(flash[:alert], style: "color:red") if flash[:alert] %>
4
+
5
+ <%%= form_with url: passwords_path do |form| %>
6
+ <%%= form.email_field :email_address, required: true, autofocus: true, autocomplete: "username", placeholder: "Enter your email address", value: params[:email_address] %><br>
7
+ <%%= form.submit "Email reset instructions" %>
8
+ <%% end %>
@@ -0,0 +1,11 @@
1
+ <%%= tag.div(flash[:alert], style: "color:red") if flash[:alert] %>
2
+ <%%= tag.div(flash[:notice], style: "color:green") if flash[:notice] %>
3
+
4
+ <%%= form_with url: session_path do |form| %>
5
+ <%%= form.email_field :email_address, required: true, autofocus: true, autocomplete: "username", placeholder: "Enter your email address", value: params[:email_address] %><br>
6
+ <%%= form.password_field :password, required: true, autocomplete: "current-password", placeholder: "Enter your password", maxlength: 72 %><br>
7
+ <%%= form.submit "Sign in" %>
8
+ <%% end %>
9
+ <br>
10
+
11
+ <%%= link_to "Forgot password?", new_password_path %>
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/time"
4
+ require "active_support/core_ext/string/starts_ends_with"
4
5
 
5
6
  module Rails
6
7
  module Generators
@@ -89,20 +90,24 @@ module Rails
89
90
  def parse_type_and_options(type)
90
91
  case type
91
92
  when /(text|binary)\{([a-z]+)\}/
92
- return $1, size: $2.to_sym
93
+ parsed_type, parsed_options = $1, { size: $2.to_sym }
93
94
  when /(string|text|binary|integer)\{(\d+)\}/
94
- return $1, limit: $2.to_i
95
+ parsed_type, parsed_options = $1, { limit: $2.to_i }
95
96
  when /decimal\{(\d+)[,.-](\d+)\}/
96
- return :decimal, precision: $1.to_i, scale: $2.to_i
97
+ parsed_type, parsed_options = :decimal, { precision: $1.to_i, scale: $2.to_i }
97
98
  when /(references|belongs_to)\{(.+)\}/
98
- type = $1
99
+ parsed_type = $1
99
100
  provided_options = $2.split(/[,.-]/)
100
- options = Hash[provided_options.map { |opt| [opt.to_sym, true] }]
101
-
102
- return type, options
101
+ parsed_options = Hash[provided_options.map { |opt| [opt.to_sym, true] }]
103
102
  else
104
- return type, {}
103
+ parsed_type, parsed_options = type&.remove("!"), {}
104
+ end
105
+
106
+ if type&.ends_with?("!")
107
+ parsed_options[:null] = false
105
108
  end
109
+
110
+ return parsed_type, parsed_options
106
111
  end
107
112
  end
108
113
 
@@ -121,9 +126,9 @@ module Rails
121
126
  when :time then :time_field
122
127
  when :datetime, :timestamp then :datetime_field
123
128
  when :date then :date_field
124
- when :text then :text_area
125
- when :rich_text then :rich_text_area
126
- when :boolean then :check_box
129
+ when :text then :textarea
130
+ when :rich_text then :rich_textarea
131
+ when :boolean then :checkbox
127
132
  when :attachment, :attachments then :file_field
128
133
  else
129
134
  :text_field
@@ -109,7 +109,7 @@ module Rails
109
109
  end
110
110
 
111
111
  def bin
112
- exclude_pattern = Regexp.union([(/rubocop/ if skip_rubocop?), (/brakeman/ if skip_brakeman?)].compact)
112
+ exclude_pattern = Regexp.union([(/thrust/ if skip_thruster?), (/rubocop/ if skip_rubocop?), (/brakeman/ if skip_brakeman?)].compact)
113
113
  directory "bin", { exclude_pattern: exclude_pattern } do |content|
114
114
  "#{shebang}\n" + content
115
115
  end
@@ -142,10 +142,8 @@ module Rails
142
142
  active_storage_config_exist = File.exist?("config/storage.yml")
143
143
  rack_cors_config_exist = File.exist?("config/initializers/cors.rb")
144
144
  assets_config_exist = File.exist?("config/initializers/assets.rb")
145
- asset_manifest_exist = File.exist?("app/assets/config/manifest.js")
146
145
  asset_app_stylesheet_exist = File.exist?("app/assets/stylesheets/application.css")
147
146
  csp_config_exist = File.exist?("config/initializers/content_security_policy.rb")
148
- permissions_policy_config_exist = File.exist?("config/initializers/permissions_policy.rb")
149
147
 
150
148
  @config_target_version = Rails.application.config.loaded_config_version || "5.0"
151
149
 
@@ -159,15 +157,11 @@ module Rails
159
157
  template "config/storage.yml"
160
158
  end
161
159
 
162
- if skip_sprockets? && skip_propshaft? && !assets_config_exist
160
+ if skip_asset_pipeline? && !assets_config_exist
163
161
  remove_file "config/initializers/assets.rb"
164
162
  end
165
163
 
166
- if skip_sprockets? && !asset_manifest_exist
167
- remove_file "app/assets/config/manifest.js"
168
- end
169
-
170
- if skip_sprockets? && !asset_app_stylesheet_exist
164
+ if skip_asset_pipeline? && !asset_app_stylesheet_exist
171
165
  remove_file "app/assets/stylesheets/application.css"
172
166
  end
173
167
 
@@ -179,10 +173,6 @@ module Rails
179
173
  unless csp_config_exist
180
174
  remove_file "config/initializers/content_security_policy.rb"
181
175
  end
182
-
183
- unless permissions_policy_config_exist
184
- remove_file "config/initializers/permissions_policy.rb"
185
- end
186
176
  end
187
177
  end
188
178
 
@@ -211,7 +201,7 @@ module Rails
211
201
  end
212
202
 
213
203
  def database_yml
214
- template "config/databases/#{options[:database]}.yml", "config/database.yml"
204
+ template database.template, "config/database.yml"
215
205
  end
216
206
 
217
207
  def db
@@ -221,7 +211,6 @@ module Rails
221
211
  def lib
222
212
  empty_directory "lib"
223
213
  empty_directory_with_keep_file "lib/tasks"
224
- empty_directory_with_keep_file "lib/assets"
225
214
  end
226
215
 
227
216
  def log
@@ -234,6 +223,10 @@ module Rails
234
223
  directory "public", "public", recursive: false
235
224
  end
236
225
 
226
+ def script
227
+ empty_directory_with_keep_file "script"
228
+ end
229
+
237
230
  def storage
238
231
  empty_directory_with_keep_file "storage"
239
232
  empty_directory_with_keep_file "tmp/storage"
@@ -247,7 +240,6 @@ module Rails
247
240
  empty_directory_with_keep_file "test/helpers"
248
241
  empty_directory_with_keep_file "test/integration"
249
242
 
250
- template "test/channels/application_cable/connection_test.rb"
251
243
  template "test/test_helper.rb"
252
244
  end
253
245
 
@@ -273,14 +265,16 @@ module Rails
273
265
  def devcontainer
274
266
  devcontainer_options = {
275
267
  database: options[:database],
276
- redis: !(options[:skip_action_cable] && options[:skip_active_job]),
268
+ redis: options[:skip_solid] && !(options[:skip_action_cable] && options[:skip_active_job]),
269
+ kamal: !options[:skip_kamal],
277
270
  system_test: depends_on_system_test?,
278
271
  active_storage: !options[:skip_active_storage],
279
272
  dev: options[:dev],
280
273
  node: using_node?,
281
- app_name: app_name
274
+ app_name: app_name,
275
+ skip_solid: options[:skip_solid],
276
+ pretend: options[:pretend]
282
277
  }
283
-
284
278
  Rails::Generators::DevcontainerGenerator.new([], devcontainer_options).invoke_all
285
279
  end
286
280
  end
@@ -311,11 +305,18 @@ module Rails
311
305
  :skip_active_job,
312
306
  :skip_active_storage,
313
307
  :skip_bootsnap,
308
+ :skip_brakeman,
309
+ :skip_ci,
314
310
  :skip_dev_gems,
311
+ :skip_docker,
315
312
  :skip_hotwire,
316
313
  :skip_javascript,
317
314
  :skip_jbuilder,
315
+ :skip_kamal,
316
+ :skip_rubocop,
317
+ :skip_solid,
318
318
  :skip_system_test,
319
+ :skip_thruster
319
320
  ],
320
321
  api: [
321
322
  :skip_asset_pipeline,
@@ -443,6 +444,11 @@ module Rails
443
444
  build(:public_directory)
444
445
  end
445
446
 
447
+ def create_script_folder
448
+ return if options[:dummy_app]
449
+ build(:script)
450
+ end
451
+
446
452
  def create_tmp_files
447
453
  build(:tmp)
448
454
  end
@@ -471,7 +477,6 @@ module Rails
471
477
  def delete_app_assets_if_api_option
472
478
  if options[:api]
473
479
  remove_dir "app/assets"
474
- remove_dir "lib/assets"
475
480
  end
476
481
  end
477
482
 
@@ -495,6 +500,7 @@ module Rails
495
500
 
496
501
  def delete_public_files_if_api_option
497
502
  if options[:api]
503
+ remove_file "public/400.html"
498
504
  remove_file "public/404.html"
499
505
  remove_file "public/406-unsupported-browser.html"
500
506
  remove_file "public/422.html"
@@ -504,14 +510,9 @@ module Rails
504
510
  end
505
511
  end
506
512
 
507
- def delete_assets_initializer_skipping_sprockets_and_propshaft
508
- if skip_sprockets? && skip_propshaft?
513
+ def delete_assets_initializer_skipping_asset_pipeline
514
+ if skip_asset_pipeline?
509
515
  remove_file "config/initializers/assets.rb"
510
- end
511
-
512
- if skip_sprockets?
513
- remove_file "app/assets/config/manifest.js"
514
- remove_dir "app/assets/config"
515
516
  remove_file "app/assets/stylesheets/application.css"
516
517
  create_file "app/assets/stylesheets/application.css", "/* Application styles */\n" unless options[:api]
517
518
  end
@@ -541,15 +542,12 @@ module Rails
541
542
  def delete_action_cable_files_skipping_action_cable
542
543
  if options[:skip_action_cable]
543
544
  remove_dir "app/javascript/channels"
544
- remove_dir "app/channels"
545
- remove_dir "test/channels"
546
545
  end
547
546
  end
548
547
 
549
548
  def delete_non_api_initializers_if_api_option
550
549
  if options[:api]
551
550
  remove_file "config/initializers/content_security_policy.rb"
552
- remove_file "config/initializers/permissions_policy.rb"
553
551
  end
554
552
  end
555
553
 
@@ -576,6 +574,8 @@ module Rails
576
574
  public_task :run_javascript
577
575
  public_task :run_hotwire
578
576
  public_task :run_css
577
+ public_task :run_kamal
578
+ public_task :run_solid
579
579
 
580
580
  def run_after_bundle_callbacks
581
581
  @after_bundle_callbacks.each(&:call)
@@ -1,11 +1,14 @@
1
- # syntax = docker/dockerfile:1
1
+ # syntax=docker/dockerfile:1
2
+ # check=error=true
2
3
 
3
4
  # This Dockerfile is designed for production, not development. Use with Kamal or build'n'run by hand:
4
- # docker build -t my-app .
5
- # docker run -d -p 80:80 -p 443:443 --name my-app -e RAILS_MASTER_KEY=<value from config/master.key> my-app
5
+ # docker build -t <%= app_name %> .
6
+ # docker run -d -p 80:<%= skip_thruster? ? 3000 : 80 %> -e RAILS_MASTER_KEY=<value from config/master.key> --name <%= app_name %> <%= app_name %>
7
+
8
+ # For a containerized dev environment, see Dev Containers: https://guides.rubyonrails.org/getting_started_with_devcontainer.html
6
9
 
7
10
  # Make sure RUBY_VERSION matches the Ruby version in .ruby-version
8
- ARG RUBY_VERSION=<%= gem_ruby_version %>
11
+ ARG RUBY_VERSION=<%= Gem.ruby_version %>
9
12
  FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base
10
13
 
11
14
  # Rails app lives here
@@ -35,10 +38,17 @@ RUN apt-get update -qq && \
35
38
  ARG NODE_VERSION=<%= node_version %>
36
39
  ARG YARN_VERSION=<%= dockerfile_yarn_version %>
37
40
  ENV PATH=/usr/local/node/bin:$PATH
41
+ <% if yarn_through_corepack? -%>
42
+ RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \
43
+ /tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
44
+ rm -rf /tmp/node-build-master
45
+ RUN corepack enable && yarn set version $YARN_VERSION
46
+ <% else -%>
38
47
  RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \
39
48
  /tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
40
49
  npm install -g yarn@$YARN_VERSION && \
41
50
  rm -rf /tmp/node-build-master
51
+ <% end -%>
42
52
 
43
53
  <% end -%>
44
54
  <% if using_bun? -%>
@@ -49,6 +59,7 @@ RUN curl -fsSL https://bun.sh/install | bash -s -- "bun-v${BUN_VERSION}"
49
59
 
50
60
  <% end -%>
51
61
  # Install application gems
62
+ COPY vendor/* ./vendor/
52
63
  COPY Gemfile Gemfile.lock ./
53
64
  RUN bundle install && \
54
65
  rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git<% if depend_on_bootsnap? -%> && \
@@ -57,12 +68,12 @@ RUN bundle install && \
57
68
  <% if using_node? -%>
58
69
  # Install node modules
59
70
  COPY package.json yarn.lock ./
60
- RUN yarn install --frozen-lockfile
71
+ RUN yarn install --immutable
61
72
 
62
73
  <% end -%>
63
74
  <% if using_bun? -%>
64
75
  # Install node modules
65
- COPY package.json bun.lockb ./
76
+ COPY package.json bun.lock* ./
66
77
  RUN bun install --frozen-lockfile
67
78
 
68
79
  <% end -%>
@@ -105,6 +116,12 @@ USER 1000:1000
105
116
  # Entrypoint prepares the database.
106
117
  ENTRYPOINT ["/rails/bin/docker-entrypoint"]
107
118
 
119
+ <% if skip_thruster? -%>
108
120
  # Start the server by default, this can be overwritten at runtime
109
121
  EXPOSE 3000
110
122
  CMD ["./bin/rails", "server"]
123
+ <% else -%>
124
+ # Start server via Thruster by default, this can be overwritten at runtime
125
+ EXPOSE 80
126
+ CMD ["./bin/thrust", "./bin/rails", "server"]
127
+ <% end -%>