railties 7.2.1.1 → 8.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +122 -278
  3. data/lib/minitest/rails_plugin.rb +1 -1
  4. data/lib/rails/application/bootstrap.rb +0 -1
  5. data/lib/rails/application/configuration.rb +15 -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 +11 -1
  9. data/lib/rails/application.rb +5 -0
  10. data/lib/rails/code_statistics.rb +128 -86
  11. data/lib/rails/code_statistics_calculator.rb +78 -76
  12. data/lib/rails/command/helpers/editor.rb +1 -1
  13. data/lib/rails/command.rb +0 -6
  14. data/lib/rails/commands/app/update_command.rb +1 -9
  15. data/lib/rails/commands/console/irb_console.rb +11 -8
  16. data/lib/rails/commands/credentials/USAGE +4 -4
  17. data/lib/rails/commands/credentials/credentials_command.rb +5 -1
  18. data/lib/rails/commands/dev/dev_command.rb +1 -1
  19. data/lib/rails/commands/devcontainer/devcontainer_command.rb +2 -1
  20. data/lib/rails/commands/stats/stats_command.rb +19 -0
  21. data/lib/rails/console/methods.rb +5 -21
  22. data/lib/rails/dev_caching.rb +2 -2
  23. data/lib/rails/engine/configuration.rb +3 -1
  24. data/lib/rails/engine/lazy_route_set.rb +114 -0
  25. data/lib/rails/engine.rb +12 -8
  26. data/lib/rails/gem_version.rb +4 -4
  27. data/lib/rails/generators/app_base.rb +46 -28
  28. data/lib/rails/generators/base.rb +0 -4
  29. data/lib/rails/generators/database.rb +101 -67
  30. data/lib/rails/generators/erb/authentication/authentication_generator.rb +15 -0
  31. data/lib/rails/generators/erb/authentication/templates/app/views/passwords/edit.html.erb +9 -0
  32. data/lib/rails/generators/erb/authentication/templates/app/views/passwords/new.html.erb +8 -0
  33. data/lib/rails/generators/erb/authentication/templates/app/views/sessions/new.html.erb +11 -0
  34. data/lib/rails/generators/generated_attribute.rb +16 -11
  35. data/lib/rails/generators/rails/app/app_generator.rb +20 -32
  36. data/lib/rails/generators/rails/app/templates/Dockerfile.tt +13 -4
  37. data/lib/rails/generators/rails/app/templates/Gemfile.tt +25 -10
  38. data/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css.tt +6 -11
  39. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +10 -3
  40. data/lib/rails/generators/rails/app/templates/bin/dev.tt +1 -0
  41. data/lib/rails/generators/rails/app/templates/bin/setup.tt +5 -8
  42. data/lib/rails/generators/rails/app/templates/bin/thrust.tt +4 -0
  43. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +23 -0
  44. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +23 -0
  45. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +40 -0
  46. data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +23 -0
  47. data/lib/rails/generators/rails/app/templates/config/deploy.yml.tt +128 -0
  48. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +12 -23
  49. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +34 -51
  50. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +5 -19
  51. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +0 -7
  52. data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +1 -1
  53. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_0.rb.tt +25 -0
  54. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +11 -2
  55. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +3 -3
  56. data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +4 -3
  57. data/lib/rails/generators/rails/app/templates/dockerignore.tt +1 -2
  58. data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +5 -1
  59. data/lib/rails/generators/rails/app/templates/gitignore.tt +1 -2
  60. data/lib/rails/generators/rails/app/templates/kamal-secrets.tt +17 -0
  61. data/lib/rails/generators/rails/app/templates/public/400.html +114 -0
  62. data/lib/rails/generators/rails/app/templates/public/404.html +113 -66
  63. data/lib/rails/generators/rails/app/templates/public/406-unsupported-browser.html +113 -65
  64. data/lib/rails/generators/rails/app/templates/public/422.html +113 -66
  65. data/lib/rails/generators/rails/app/templates/public/500.html +113 -65
  66. data/lib/rails/generators/rails/app/templates/public/icon.png +0 -0
  67. data/lib/rails/generators/rails/app/templates/public/icon.svg +2 -2
  68. data/lib/rails/generators/rails/authentication/USAGE +6 -0
  69. data/lib/rails/generators/rails/authentication/authentication_generator.rb +56 -0
  70. data/lib/rails/generators/rails/authentication/templates/app/controllers/concerns/authentication.rb.tt +55 -0
  71. data/lib/rails/generators/rails/authentication/templates/app/controllers/passwords_controller.rb.tt +33 -0
  72. data/lib/rails/generators/rails/authentication/templates/app/controllers/sessions_controller.rb.tt +21 -0
  73. data/lib/rails/generators/rails/authentication/templates/app/mailers/passwords_mailer.rb.tt +6 -0
  74. data/lib/rails/generators/rails/authentication/templates/app/models/current.rb.tt +4 -0
  75. data/lib/rails/generators/rails/authentication/templates/app/models/session.rb.tt +3 -0
  76. data/lib/rails/generators/rails/authentication/templates/app/models/user.rb.tt +6 -0
  77. data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.html.erb.tt +4 -0
  78. data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.text.erb.tt +2 -0
  79. data/lib/rails/generators/rails/authentication/templates/test/mailers/previews/passwords_mailer_preview.rb.tt +7 -0
  80. data/lib/rails/generators/rails/credentials/templates/credentials.yml.tt +4 -0
  81. data/lib/rails/generators/rails/db/system/change/change_generator.rb +1 -1
  82. data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +10 -3
  83. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/Dockerfile.tt +1 -1
  84. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +1 -1
  85. data/lib/rails/generators/rails/plugin/plugin_generator.rb +11 -11
  86. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +1 -1
  87. data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +1 -1
  88. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +2 -2
  89. data/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt +2 -2
  90. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt +3 -3
  91. data/lib/rails/generators/rails/script/USAGE +18 -0
  92. data/lib/rails/generators/rails/script/script_generator.rb +18 -0
  93. data/lib/rails/generators/rails/script/templates/script.rb.tt +3 -0
  94. data/lib/rails/generators/test_unit/authentication/authentication_generator.rb +14 -0
  95. data/lib/rails/generators/test_unit/authentication/templates/test/fixtures/users.yml.tt +9 -0
  96. data/lib/rails/generators/test_unit/authentication/templates/test/models/user_test.rb.tt +7 -0
  97. data/lib/rails/generators.rb +7 -2
  98. data/lib/rails/info_controller.rb +10 -2
  99. data/lib/rails/rack/silence_request.rb +33 -0
  100. data/lib/rails/rack.rb +1 -0
  101. data/lib/rails/railtie.rb +13 -13
  102. data/lib/rails/source_annotation_extractor.rb +31 -14
  103. data/lib/rails/tasks/statistics.rake +13 -28
  104. data/lib/rails/templates/rails/info/notes.html.erb +65 -0
  105. data/lib/rails/test_unit/runner.rb +1 -0
  106. metadata +44 -23
  107. data/lib/rails/console/app.rb +0 -8
  108. data/lib/rails/console/helpers.rb +0 -8
  109. data/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt +0 -2
  110. data/lib/rails/generators/rails/app/templates/app/channels/application_cable/channel.rb.tt +0 -4
  111. data/lib/rails/generators/rails/app/templates/app/channels/application_cable/connection.rb.tt +0 -4
  112. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_2.rb.tt +0 -70
  113. data/lib/rails/generators/rails/app/templates/config/initializers/permissions_policy.rb.tt +0 -13
  114. data/lib/rails/generators/rails/app/templates/test/channels/application_cable/connection_test.rb.tt +0 -13
  115. data/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js.tt +0 -10
  116. data/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js.tt +0 -6
  117. data/lib/rails/generators/rails/plugin/templates/rails/javascripts.js.tt +0 -17
@@ -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,7 +265,8 @@ 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],
@@ -286,10 +279,6 @@ module Rails
286
279
  end
287
280
 
288
281
  module Generators
289
- # We need to store the RAILS_DEV_PATH in a constant, otherwise the path
290
- # can change in Ruby 1.8.7 when we FileUtils.cd.
291
- RAILS_DEV_PATH = File.expand_path("../../../../../..", __dir__)
292
-
293
282
  class AppGenerator < AppBase
294
283
  # :stopdoc:
295
284
 
@@ -447,6 +436,11 @@ module Rails
447
436
  build(:public_directory)
448
437
  end
449
438
 
439
+ def create_script_folder
440
+ return if options[:dummy_app]
441
+ build(:script)
442
+ end
443
+
450
444
  def create_tmp_files
451
445
  build(:tmp)
452
446
  end
@@ -475,7 +469,6 @@ module Rails
475
469
  def delete_app_assets_if_api_option
476
470
  if options[:api]
477
471
  remove_dir "app/assets"
478
- remove_dir "lib/assets"
479
472
  end
480
473
  end
481
474
 
@@ -499,6 +492,7 @@ module Rails
499
492
 
500
493
  def delete_public_files_if_api_option
501
494
  if options[:api]
495
+ remove_file "public/400.html"
502
496
  remove_file "public/404.html"
503
497
  remove_file "public/406-unsupported-browser.html"
504
498
  remove_file "public/422.html"
@@ -508,14 +502,9 @@ module Rails
508
502
  end
509
503
  end
510
504
 
511
- def delete_assets_initializer_skipping_sprockets_and_propshaft
512
- if skip_sprockets? && skip_propshaft?
505
+ def delete_assets_initializer_skipping_asset_pipeline
506
+ if skip_asset_pipeline?
513
507
  remove_file "config/initializers/assets.rb"
514
- end
515
-
516
- if skip_sprockets?
517
- remove_file "app/assets/config/manifest.js"
518
- remove_dir "app/assets/config"
519
508
  remove_file "app/assets/stylesheets/application.css"
520
509
  create_file "app/assets/stylesheets/application.css", "/* Application styles */\n" unless options[:api]
521
510
  end
@@ -545,15 +534,12 @@ module Rails
545
534
  def delete_action_cable_files_skipping_action_cable
546
535
  if options[:skip_action_cable]
547
536
  remove_dir "app/javascript/channels"
548
- remove_dir "app/channels"
549
- remove_dir "test/channels"
550
537
  end
551
538
  end
552
539
 
553
540
  def delete_non_api_initializers_if_api_option
554
541
  if options[:api]
555
542
  remove_file "config/initializers/content_security_policy.rb"
556
- remove_file "config/initializers/permissions_policy.rb"
557
543
  end
558
544
  end
559
545
 
@@ -580,6 +566,8 @@ module Rails
580
566
  public_task :run_javascript
581
567
  public_task :run_hotwire
582
568
  public_task :run_css
569
+ public_task :run_kamal
570
+ public_task :run_solid
583
571
 
584
572
  def run_after_bundle_callbacks
585
573
  @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
@@ -105,6 +108,12 @@ USER 1000:1000
105
108
  # Entrypoint prepares the database.
106
109
  ENTRYPOINT ["/rails/bin/docker-entrypoint"]
107
110
 
111
+ <% if skip_thruster? -%>
108
112
  # Start the server by default, this can be overwritten at runtime
109
113
  EXPOSE 3000
110
114
  CMD ["./bin/rails", "server"]
115
+ <% else -%>
116
+ # Start server via Thruster by default, this can be overwritten at runtime
117
+ EXPOSE 80
118
+ CMD ["./bin/thrust", "./bin/rails", "server"]
119
+ <% end -%>
@@ -5,20 +5,40 @@ source "https://rubygems.org"
5
5
  <% end -%>
6
6
  <% unless options.minimal? -%>
7
7
 
8
- # Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis]
9
- # gem "kredis"
10
-
11
8
  # Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword]
12
9
  # gem "bcrypt", "~> 3.1.7"
13
10
  <% end -%>
14
11
 
15
12
  # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
16
- gem "tzinfo-data", platforms: %i[ <%= bundler_windows_platforms %> jruby ]
13
+ gem "tzinfo-data", platforms: %i[ windows jruby ]
14
+ <% unless options.skip_solid? -%>
15
+
16
+ <% if options.skip_action_cable? -%>
17
+ # Use the database-backed adapters for Rails.cache and Active Job
18
+ <% else -%>
19
+ # Use the database-backed adapters for Rails.cache, Active Job, and Action Cable
20
+ <% end -%>
21
+ gem "solid_cache"
22
+ gem "solid_queue"
23
+ <% unless options.skip_action_cable? -%>
24
+ gem "solid_cable"
25
+ <% end -%>
26
+ <% end -%>
17
27
  <% if depend_on_bootsnap? -%>
18
28
 
19
29
  # Reduces boot times through caching; required in config/boot.rb
20
30
  gem "bootsnap", require: false
21
31
  <% end -%>
32
+ <% unless options.skip_kamal? -%>
33
+
34
+ # Deploy this application anywhere as a Docker container [https://kamal-deploy.org]
35
+ gem "kamal", require: false
36
+ <% end -%>
37
+ <% unless options.skip_thruster? -%>
38
+
39
+ # Add HTTP asset caching/compression and X-Sendfile acceleration to Puma [https://github.com/basecamp/thruster/]
40
+ gem "thruster", require: false
41
+ <% end -%>
22
42
  <% unless skip_active_storage? -%>
23
43
 
24
44
  # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
@@ -33,7 +53,7 @@ gem "bootsnap", require: false
33
53
 
34
54
  group :development, :test do
35
55
  # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
36
- gem "debug", platforms: %i[ mri <%= bundler_windows_platforms %> ], require: "debug/prelude"
56
+ gem "debug", platforms: %i[ mri windows ], require: "debug/prelude"
37
57
  <%- unless options.skip_brakeman? -%>
38
58
 
39
59
  # Static analysis for security vulnerabilities [https://brakemanscanner.org/]
@@ -51,11 +71,6 @@ end
51
71
  group :development do
52
72
  # Use console on exceptions pages [https://github.com/rails/web-console]
53
73
  gem "web-console"
54
- <%- if RUBY_VERSION < "3.2" -%>
55
-
56
- # Highlight the fine-grained location where an error occurred [https://github.com/ruby/error_highlight]
57
- gem "error_highlight", ">= 0.4.0", platforms: [:ruby]
58
- <%- end -%>
59
74
  end
60
75
  <%- end -%>
61
76
 
@@ -1,15 +1,10 @@
1
1
  /*
2
- * This is a manifest file that'll be compiled into application.css, which will include all the files
3
- * listed below.
2
+ * This is a manifest file that'll be compiled into application.css.
4
3
  *
5
- * Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's
6
- * vendor/assets/stylesheets directory can be referenced here using a relative path.
4
+ * With Propshaft, assets are served efficiently without preprocessing steps. You can still include
5
+ * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
6
+ * cascading order, meaning styles declared later in the document or manifest will override earlier ones,
7
+ * depending on specificity.
7
8
  *
8
- * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
- * compiled file so the styles you add here take precedence over styles defined in any other CSS
10
- * files in this directory. Styles in this file should be added after the last require_* statement.
11
- * It is generally better to create a new file per style scope.
12
- *
13
- *= require_tree .
14
- *= require_self
9
+ * Consider organizing styles into separate files for maintainability.
15
10
  */
@@ -4,19 +4,26 @@
4
4
  <title><%%= content_for(:title) || "<%= app_name.titleize %>" %></title>
5
5
  <meta name="viewport" content="width=device-width,initial-scale=1">
6
6
  <meta name="apple-mobile-web-app-capable" content="yes">
7
+ <meta name="mobile-web-app-capable" content="yes">
7
8
  <%%= csrf_meta_tags %>
8
9
  <%%= csp_meta_tag %>
9
10
 
10
11
  <%%= yield :head %>
11
12
 
12
- <link rel="manifest" href="/manifest.json">
13
+ <%%# Enable PWA manifest for installable apps (make sure to enable in config/routes.rb too!) %>
14
+ <%%#= tag.link rel: "manifest", href: pwa_manifest_path(format: :json) %>
15
+
13
16
  <link rel="icon" href="/icon.png" type="image/png">
14
17
  <link rel="icon" href="/icon.svg" type="image/svg+xml">
15
18
  <link rel="apple-touch-icon" href="/icon.png">
19
+
20
+ <%- style_link_target = options[:skip_asset_pipeline] ? "\"application\"" : ":app" -%>
16
21
  <%- if options[:skip_hotwire] || options[:skip_javascript] -%>
17
- <%%= stylesheet_link_tag "application" %>
22
+ <%%# Includes all stylesheet files in app/assets/stylesheets %>
23
+ <%%= stylesheet_link_tag <%= style_link_target %> %>
18
24
  <%- else -%>
19
- <%%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
25
+ <%%# Includes all stylesheet files in app/assets/stylesheets %>
26
+ <%%= stylesheet_link_tag <%= style_link_target %>, "data-turbo-track": "reload" %>
20
27
  <%- end -%>
21
28
  </head>
22
29
 
@@ -0,0 +1 @@
1
+ exec "./bin/rails", "server", *ARGV
@@ -1,7 +1,6 @@
1
1
  require "fileutils"
2
2
 
3
3
  APP_ROOT = File.expand_path("..", __dir__)
4
- APP_NAME = "<%= app_name.dasherize %>"
5
4
 
6
5
  def system!(*args)
7
6
  system(*args, exception: true)
@@ -13,7 +12,6 @@ FileUtils.chdir APP_ROOT do
13
12
  # Add necessary setup steps to this file.
14
13
 
15
14
  puts "== Installing dependencies =="
16
- system! "gem install bundler --conservative"
17
15
  system("bundle check") || system!("bundle install")
18
16
  <% if using_node? -%>
19
17
 
@@ -38,10 +36,9 @@ FileUtils.chdir APP_ROOT do
38
36
  puts "\n== Removing old logs and tempfiles =="
39
37
  system! "bin/rails log:clear tmp:clear"
40
38
 
41
- puts "\n== Restarting application server =="
42
- system! "bin/rails restart"
43
-
44
- # puts "\n== Configuring puma-dev =="
45
- # system "ln -nfs #{APP_ROOT} ~/.puma-dev/#{APP_NAME}"
46
- # system "curl -Is https://#{APP_NAME}.test/up | head -n 1"
39
+ unless ARGV.include?("--skip-server")
40
+ puts "\n== Starting development server =="
41
+ STDOUT.flush # flush the output before exec(2) so that it displays
42
+ exec "bin/dev"
43
+ end
47
44
  end
@@ -0,0 +1,4 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+
4
+ load Gem.bin_path("thruster", "thrust")
@@ -52,8 +52,31 @@ test:
52
52
  # Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
53
53
  # for a full overview on how database connection configuration can be specified.
54
54
  #
55
+ <%- if options.skip_solid? -%>
55
56
  production:
56
57
  <<: *default
57
58
  database: <%= app_name %>_production
58
59
  username: <%= app_name %>
59
60
  password: <%%= ENV["<%= app_name.upcase %>_DATABASE_PASSWORD"] %>
61
+ <%- else -%>
62
+ production:
63
+ primary: &primary_production
64
+ <<: *default
65
+ database: <%= app_name %>_production
66
+ username: <%= app_name %>
67
+ password: <%%= ENV["<%= app_name.upcase %>_DATABASE_PASSWORD"] %>
68
+ cache:
69
+ <<: *primary_production
70
+ database: <%= app_name %>_production_cache
71
+ migrations_paths: db/cache_migrate
72
+ queue:
73
+ <<: *primary_production
74
+ database: <%= app_name %>_production_queue
75
+ migrations_paths: db/queue_migrate
76
+ <%- unless options.skip_action_cable? -%>
77
+ cable:
78
+ <<: *primary_production
79
+ database: <%= app_name %>_production_cable
80
+ migrations_paths: db/cable_migrate
81
+ <%- end -%>
82
+ <%- end -%>
@@ -84,8 +84,31 @@ test:
84
84
  # Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
85
85
  # for a full overview on how database connection configuration can be specified.
86
86
  #
87
+ <%- if options.skip_solid? -%>
87
88
  production:
88
89
  <<: *default
89
90
  database: <%= app_name %>_production
90
91
  username: <%= app_name %>
91
92
  password: <%%= ENV["<%= app_name.upcase %>_DATABASE_PASSWORD"] %>
93
+ <%- else -%>
94
+ production:
95
+ primary: &primary_production
96
+ <<: *default
97
+ database: <%= app_name %>_production
98
+ username: <%= app_name %>
99
+ password: <%%= ENV["<%= app_name.upcase %>_DATABASE_PASSWORD"] %>
100
+ cache:
101
+ <<: *primary_production
102
+ database: <%= app_name %>_production_cache
103
+ migrations_paths: db/cache_migrate
104
+ queue:
105
+ <<: *primary_production
106
+ database: <%= app_name %>_production_queue
107
+ migrations_paths: db/queue_migrate
108
+ <%- unless options.skip_action_cable? -%>
109
+ cable:
110
+ <<: *primary_production
111
+ database: <%= app_name %>_production_cable
112
+ migrations_paths: db/cable_migrate
113
+ <%- end -%>
114
+ <%- end -%>
@@ -21,12 +21,52 @@ test:
21
21
  database: storage/test.sqlite3
22
22
 
23
23
 
24
+ <%- if options.skip_kamal? -%>
24
25
  # SQLite3 write its data on the local filesystem, as such it requires
25
26
  # persistent disks. If you are deploying to a managed service, you should
26
27
  # make sure it provides disk persistence, as many don't.
27
28
  #
28
29
  # Similarly, if you deploy your application as a Docker container, you must
29
30
  # ensure the database is located in a persisted volume.
31
+ <%- if options.skip_solid? -%>
30
32
  production:
31
33
  <<: *default
32
34
  # database: path/to/persistent/storage/production.sqlite3
35
+ <%- else -%>
36
+ production:
37
+ primary:
38
+ <<: *default
39
+ # database: path/to/persistent/storage/production.sqlite3
40
+ cache:
41
+ <<: *default
42
+ # database: path/to/persistent/storage/production_cache.sqlite3
43
+ migrations_paths: db/cache_migrate
44
+ <%- end -%>
45
+ <%- else -%>
46
+ # Store production database in the storage/ directory, which by default
47
+ # is mounted as a persistent Docker volume in config/deploy.yml.
48
+ <%- if options.skip_solid? -%>
49
+ production:
50
+ <<: *default
51
+ database: storage/production.sqlite3
52
+ <%- else -%>
53
+ production:
54
+ primary:
55
+ <<: *default
56
+ database: storage/production.sqlite3
57
+ cache:
58
+ <<: *default
59
+ database: storage/production_cache.sqlite3
60
+ migrations_paths: db/cache_migrate
61
+ queue:
62
+ <<: *default
63
+ database: storage/production_queue.sqlite3
64
+ migrations_paths: db/queue_migrate
65
+ <%- unless options.skip_action_cable? -%>
66
+ cable:
67
+ <<: *default
68
+ database: storage/production_cable.sqlite3
69
+ migrations_paths: db/cable_migrate
70
+ <%- end -%>
71
+ <%- end -%>
72
+ <%- end -%>
@@ -52,8 +52,31 @@ test:
52
52
  # Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
53
53
  # for a full overview on how database connection configuration can be specified.
54
54
  #
55
+ <%- if options.skip_solid? -%>
55
56
  production:
56
57
  <<: *default
57
58
  database: <%= app_name %>_production
58
59
  username: <%= app_name %>
59
60
  password: <%%= ENV["<%= app_name.upcase %>_DATABASE_PASSWORD"] %>
61
+ <%- else -%>
62
+ production:
63
+ primary: &primary_production
64
+ <<: *default
65
+ database: <%= app_name %>_production
66
+ username: <%= app_name %>
67
+ password: <%%= ENV["<%= app_name.upcase %>_DATABASE_PASSWORD"] %>
68
+ cache:
69
+ <<: *primary_production
70
+ database: <%= app_name %>_production_cache
71
+ migrations_paths: db/cache_migrate
72
+ queue:
73
+ <<: *primary_production
74
+ database: <%= app_name %>_production_queue
75
+ migrations_paths: db/queue_migrate
76
+ <%- unless options.skip_action_cable? -%>
77
+ cable:
78
+ <<: *primary_production
79
+ database: <%= app_name %>_production_cable
80
+ migrations_paths: db/cable_migrate
81
+ <%- end -%>
82
+ <%- end -%>