railties 6.1.4.1 → 7.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +113 -344
  3. data/MIT-LICENSE +1 -1
  4. data/RDOC_MAIN.rdoc +16 -16
  5. data/README.rdoc +0 -1
  6. data/lib/rails/all.rb +0 -1
  7. data/lib/rails/app_updater.rb +3 -5
  8. data/lib/rails/application/bootstrap.rb +21 -5
  9. data/lib/rails/application/configuration.rb +64 -28
  10. data/lib/rails/application/default_middleware_stack.rb +7 -3
  11. data/lib/rails/application/finisher.rb +42 -85
  12. data/lib/rails/application/routes_reloader.rb +8 -0
  13. data/lib/rails/application.rb +24 -50
  14. data/lib/rails/application_controller.rb +2 -2
  15. data/lib/rails/autoloaders/inflector.rb +21 -0
  16. data/lib/rails/autoloaders.rb +12 -16
  17. data/lib/rails/code_statistics.rb +2 -2
  18. data/lib/rails/code_statistics_calculator.rb +10 -1
  19. data/lib/rails/command/base.rb +26 -12
  20. data/lib/rails/command/behavior.rb +1 -1
  21. data/lib/rails/command/environment_argument.rb +1 -1
  22. data/lib/rails/command.rb +8 -5
  23. data/lib/rails/commands/credentials/USAGE +4 -2
  24. data/lib/rails/commands/credentials/credentials_command/diffing.rb +26 -16
  25. data/lib/rails/commands/credentials/credentials_command.rb +8 -3
  26. data/lib/rails/commands/dbconsole/dbconsole_command.rb +10 -11
  27. data/lib/rails/commands/help/USAGE +3 -2
  28. data/lib/rails/commands/runner/runner_command.rb +3 -2
  29. data/lib/rails/commands/server/server_command.rb +2 -5
  30. data/lib/rails/configuration.rb +18 -23
  31. data/lib/rails/engine/configuration.rb +3 -3
  32. data/lib/rails/engine.rb +18 -24
  33. data/lib/rails/gem_version.rb +4 -4
  34. data/lib/rails/generators/actions/create_migration.rb +2 -4
  35. data/lib/rails/generators/actions.rb +35 -13
  36. data/lib/rails/generators/app_base.rb +99 -105
  37. data/lib/rails/generators/app_name.rb +1 -1
  38. data/lib/rails/generators/base.rb +9 -13
  39. data/lib/rails/generators/erb/scaffold/scaffold_generator.rb +2 -0
  40. data/lib/rails/generators/erb/scaffold/templates/_form.html.erb.tt +8 -8
  41. data/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt +8 -4
  42. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +6 -28
  43. data/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt +7 -3
  44. data/lib/rails/generators/erb/scaffold/templates/partial.html.erb.tt +20 -0
  45. data/lib/rails/generators/erb/scaffold/templates/show.html.erb.tt +8 -17
  46. data/lib/rails/generators/erb.rb +1 -1
  47. data/lib/rails/generators/generated_attribute.rb +45 -9
  48. data/lib/rails/generators/migration.rb +2 -6
  49. data/lib/rails/generators/model_helpers.rb +1 -1
  50. data/lib/rails/generators/named_base.rb +1 -1
  51. data/lib/rails/generators/rails/app/app_generator.rb +53 -91
  52. data/lib/rails/generators/rails/app/templates/Gemfile.tt +44 -50
  53. data/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css.tt +2 -2
  54. data/lib/rails/generators/rails/app/templates/app/mailers/application_mailer.rb.tt +2 -2
  55. data/lib/rails/generators/rails/app/templates/app/models/application_record.rb.tt +1 -1
  56. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +3 -9
  57. data/lib/rails/generators/rails/app/templates/bin/rails.tt +1 -4
  58. data/lib/rails/generators/rails/app/templates/bin/rake.tt +0 -3
  59. data/lib/rails/generators/rails/app/templates/bin/setup.tt +9 -14
  60. data/lib/rails/generators/rails/app/templates/config/application.rb.tt +0 -1
  61. data/lib/rails/generators/rails/app/templates/config/boot.rb.tt +1 -1
  62. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +2 -2
  63. data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt +3 -3
  64. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +3 -3
  65. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +2 -2
  66. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +3 -3
  67. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +2 -2
  68. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +3 -3
  69. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +1 -1
  70. data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +5 -5
  71. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +6 -12
  72. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +21 -17
  73. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +6 -11
  74. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +1 -5
  75. data/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +19 -25
  76. data/lib/rails/generators/rails/app/templates/config/initializers/cors.rb.tt +2 -2
  77. data/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb.tt +4 -4
  78. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_0.rb.tt +121 -0
  79. data/lib/rails/generators/rails/app/templates/config/locales/en.yml +3 -3
  80. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +1 -1
  81. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +4 -1
  82. data/lib/rails/generators/rails/app/templates/config/storage.yml.tt +5 -5
  83. data/lib/rails/generators/rails/app/templates/db/seeds.rb.tt +2 -2
  84. data/lib/rails/generators/rails/app/templates/gitattributes.tt +0 -5
  85. data/lib/rails/generators/rails/app/templates/gitignore.tt +3 -1
  86. data/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt +1 -1
  87. data/lib/rails/generators/rails/controller/controller_generator.rb +1 -2
  88. data/lib/rails/generators/rails/controller/templates/controller.rb.tt +0 -4
  89. data/lib/rails/generators/rails/db/system/change/change_generator.rb +1 -1
  90. data/lib/rails/generators/rails/generator/templates/%file_name%_generator.rb.tt +1 -1
  91. data/lib/rails/generators/rails/plugin/plugin_generator.rb +40 -15
  92. data/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt +7 -3
  93. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +9 -9
  94. data/lib/rails/generators/rails/plugin/templates/README.md.tt +1 -1
  95. data/lib/rails/generators/rails/plugin/templates/app/mailers/%namespaced_name%/application_mailer.rb.tt +2 -2
  96. data/lib/rails/generators/rails/plugin/templates/app/views/layouts/%namespaced_name%/application.html.erb.tt +0 -3
  97. data/lib/rails/generators/rails/plugin/templates/bin/rails.tt +4 -5
  98. data/lib/rails/generators/rails/plugin/templates/gitignore.tt +0 -5
  99. data/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb.tt +2 -2
  100. data/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/version.rb.tt +1 -1
  101. data/lib/rails/generators/rails/plugin/templates/rails/boot.rb.tt +2 -2
  102. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +3 -3
  103. data/lib/rails/generators/rails/scaffold/scaffold_generator.rb +0 -19
  104. data/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt +1 -5
  105. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt +6 -10
  106. data/lib/rails/generators/resource_helpers.rb +2 -2
  107. data/lib/rails/generators/test_unit/generator/templates/generator_test.rb.tt +1 -1
  108. data/lib/rails/generators/test_unit/model/templates/fixtures.yml.tt +2 -2
  109. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +3 -3
  110. data/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt +5 -5
  111. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt +2 -2
  112. data/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt +9 -11
  113. data/lib/rails/generators/testing/behaviour.rb +1 -2
  114. data/lib/rails/generators.rb +9 -22
  115. data/lib/rails/info.rb +1 -1
  116. data/lib/rails/info_controller.rb +1 -3
  117. data/lib/rails/initializable.rb +1 -1
  118. data/lib/rails/mailers_controller.rb +2 -4
  119. data/lib/rails/rack/logger.rb +0 -1
  120. data/lib/rails/railtie/configuration.rb +1 -2
  121. data/lib/rails/railtie.rb +27 -10
  122. data/lib/rails/ruby_version_check.rb +3 -3
  123. data/lib/rails/secrets.rb +4 -1
  124. data/lib/rails/tasks/framework.rake +2 -8
  125. data/lib/rails/tasks/statistics.rake +3 -1
  126. data/lib/rails/tasks/tmp.rake +8 -1
  127. data/lib/rails/tasks/yarn.rake +8 -9
  128. data/lib/rails/tasks/zeitwerk.rake +2 -10
  129. data/lib/rails/templates/layouts/application.html.erb +15 -0
  130. data/lib/rails/templates/rails/mailers/email.html.erb +13 -11
  131. data/lib/rails/templates/rails/welcome/index.html.erb +3 -0
  132. data/lib/rails/test_unit/railtie.rb +0 -4
  133. data/lib/rails/test_unit/runner.rb +16 -9
  134. data/lib/rails/test_unit/testing.rake +4 -9
  135. data/lib/rails/welcome_controller.rb +1 -0
  136. data/lib/rails.rb +5 -0
  137. metadata +34 -37
  138. data/lib/rails/command/spellchecker.rb +0 -57
  139. data/lib/rails/generators/css/assets/assets_generator.rb +0 -15
  140. data/lib/rails/generators/css/assets/templates/stylesheet.css +0 -4
  141. data/lib/rails/generators/css/scaffold/scaffold_generator.rb +0 -18
  142. data/lib/rails/generators/rails/app/templates/app/javascript/channels/consumer.js +0 -6
  143. data/lib/rails/generators/rails/app/templates/app/javascript/channels/index.js +0 -5
  144. data/lib/rails/generators/rails/app/templates/app/javascript/packs/application.js.tt +0 -23
  145. data/lib/rails/generators/rails/app/templates/bin/spring.tt +0 -13
  146. data/lib/rails/generators/rails/app/templates/bin/yarn.tt +0 -16
  147. data/lib/rails/generators/rails/app/templates/config/initializers/application_controller_renderer.rb.tt +0 -8
  148. data/lib/rails/generators/rails/app/templates/config/initializers/backtrace_silencers.rb.tt +0 -8
  149. data/lib/rails/generators/rails/app/templates/config/initializers/cookies_serializer.rb.tt +0 -5
  150. data/lib/rails/generators/rails/app/templates/config/initializers/mime_types.rb.tt +0 -4
  151. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_1.rb.tt +0 -67
  152. data/lib/rails/generators/rails/app/templates/config/initializers/wrap_parameters.rb.tt +0 -16
  153. data/lib/rails/generators/rails/app/templates/config/spring.rb.tt +0 -6
  154. data/lib/rails/generators/rails/app/templates/package.json.tt +0 -11
  155. data/lib/rails/generators/rails/assets/USAGE +0 -16
  156. data/lib/rails/generators/rails/assets/assets_generator.rb +0 -26
  157. data/lib/rails/generators/rails/assets/templates/stylesheet.css +0 -4
  158. data/lib/rails/generators/rails/scaffold/templates/scaffold.css +0 -80
@@ -30,9 +30,6 @@ module Rails
30
30
  class_option :database, type: :string, aliases: "-d", default: "sqlite3",
31
31
  desc: "Preconfigure for selected database (options: #{DATABASES.join('/')})"
32
32
 
33
- class_option :skip_gemfile, type: :boolean, default: false,
34
- desc: "Don't create a Gemfile"
35
-
36
33
  class_option :skip_git, type: :boolean, aliases: "-G", default: false,
37
34
  desc: "Skip .gitignore file"
38
35
 
@@ -58,26 +55,19 @@ module Rails
58
55
  class_option :skip_active_storage, type: :boolean, default: false,
59
56
  desc: "Skip Active Storage files"
60
57
 
61
- class_option :skip_puma, type: :boolean, aliases: "-P", default: false,
62
- desc: "Skip Puma related files"
63
-
64
58
  class_option :skip_action_cable, type: :boolean, aliases: "-C", default: false,
65
59
  desc: "Skip Action Cable files"
66
60
 
67
- class_option :skip_sprockets, type: :boolean, aliases: "-S", default: false,
68
- desc: "Skip Sprockets files"
61
+ class_option :skip_asset_pipeline, type: :boolean, aliases: "-A", default: false
69
62
 
70
- class_option :skip_spring, type: :boolean, default: false,
71
- desc: "Don't install Spring application preloader"
72
-
73
- class_option :skip_listen, type: :boolean, default: false,
74
- desc: "Don't generate configuration that depends on the listen gem"
63
+ class_option :asset_pipeline, type: :string, aliases: "-a", default: "sprockets",
64
+ desc: "Choose your asset pipeline [options: sprockets (default), propshaft]"
75
65
 
76
66
  class_option :skip_javascript, type: :boolean, aliases: "-J", default: name == "plugin",
77
67
  desc: "Skip JavaScript files"
78
68
 
79
- class_option :skip_turbolinks, type: :boolean, default: false,
80
- desc: "Skip turbolinks gem"
69
+ class_option :skip_hotwire, type: :boolean, default: false,
70
+ desc: "Skip Hotwire integration"
81
71
 
82
72
  class_option :skip_jbuilder, type: :boolean, default: false,
83
73
  desc: "Skip jbuilder gem"
@@ -97,7 +87,7 @@ module Rails
97
87
  class_option :edge, type: :boolean, default: false,
98
88
  desc: "Set up the #{name} with Gemfile pointing to Rails repository"
99
89
 
100
- class_option :master, type: :boolean, default: false,
90
+ class_option :main, type: :boolean, default: false, aliases: "--master",
101
91
  desc: "Set up the #{name} with Gemfile pointing to Rails repository main branch"
102
92
 
103
93
  class_option :rc, type: :string, default: nil,
@@ -110,47 +100,23 @@ module Rails
110
100
  desc: "Show this help message and quit"
111
101
  end
112
102
 
113
- def initialize(positional_argv, option_argv, *)
114
- @argv = [*positional_argv, *option_argv]
103
+ def initialize(*)
115
104
  @gem_filter = lambda { |gem| true }
116
- @extra_entries = []
117
105
  super
118
106
  end
119
107
 
120
108
  private
121
- def gemfile_entry(name, *args) # :doc:
122
- options = args.extract_options!
123
- version = args.first
124
- github = options[:github]
125
- path = options[:path]
126
-
127
- if github
128
- @extra_entries << GemfileEntry.github(name, github)
129
- elsif path
130
- @extra_entries << GemfileEntry.path(name, path)
131
- else
132
- @extra_entries << GemfileEntry.version(name, version)
133
- end
134
- self
135
- end
136
-
137
109
  def gemfile_entries # :doc:
138
110
  [rails_gemfile_entry,
111
+ asset_pipeline_gemfile_entry,
139
112
  database_gemfile_entry,
140
113
  web_server_gemfile_entry,
141
- assets_gemfile_entry,
142
- webpacker_gemfile_entry,
143
114
  javascript_gemfile_entry,
115
+ hotwire_gemfile_entry,
116
+ css_gemfile_entry,
144
117
  jbuilder_gemfile_entry,
145
118
  psych_gemfile_entry,
146
- cable_gemfile_entry,
147
- @extra_entries].flatten.find_all(&@gem_filter)
148
- end
149
-
150
- def add_gem_entry_filter # :doc:
151
- @gem_filter = lambda { |next_filter, entry|
152
- yield(entry) && next_filter.call(entry)
153
- }.curry[@gem_filter]
119
+ cable_gemfile_entry].flatten.find_all(&@gem_filter)
154
120
  end
155
121
 
156
122
  def builder # :doc:
@@ -173,14 +139,9 @@ module Rails
173
139
  end
174
140
 
175
141
  def apply_rails_template # :doc:
176
- original_argv = ARGV.dup
177
- ARGV.replace(@argv)
178
-
179
142
  apply rails_template if rails_template
180
143
  rescue Thor::Error, LoadError, Errno::ENOENT => e
181
144
  raise Error, "The template [#{rails_template}] could not be loaded. Error: #{e}"
182
- ensure
183
- ARGV.replace(original_argv)
184
145
  end
185
146
 
186
147
  def set_default_accessors! # :doc:
@@ -190,7 +151,7 @@ module Rails
190
151
  when /^https?:\/\//
191
152
  options[:template]
192
153
  when String
193
- File.expand_path(options[:template], Dir.pwd)
154
+ File.expand_path(`echo #{options[:template]}`.strip)
194
155
  else
195
156
  options[:template]
196
157
  end
@@ -200,13 +161,24 @@ module Rails
200
161
  return [] if options[:skip_active_record]
201
162
  gem_name, gem_version = gem_for_database
202
163
  GemfileEntry.version gem_name, gem_version,
203
- "Use #{options[:database]} as the database for Active Record"
164
+ "Use #{options[:database]} as the database for Active Record"
204
165
  end
205
166
 
206
167
  def web_server_gemfile_entry # :doc:
207
- return [] if options[:skip_puma]
208
- comment = "Use Puma as the app server"
209
- GemfileEntry.new("puma", "~> 5.0", comment)
168
+ GemfileEntry.new "puma", "~> 5.0", "Use the Puma web server [https://github.com/puma/puma]"
169
+ end
170
+
171
+ def asset_pipeline_gemfile_entry
172
+ return [] if options[:skip_asset_pipeline]
173
+
174
+ if options[:asset_pipeline] == "sprockets"
175
+ GemfileEntry.version "sprockets-rails", ">= 3.4.1",
176
+ "The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]"
177
+ elsif options[:asset_pipeline] == "propshaft"
178
+ GemfileEntry.version "propshaft", ">= 0.4.1", "The modern asset pipeline for Rails [https://github.com/rails/propshaft/]"
179
+ else
180
+ []
181
+ end
210
182
  end
211
183
 
212
184
  def include_all_railties? # :doc:
@@ -215,7 +187,6 @@ module Rails
215
187
  :skip_active_record,
216
188
  :skip_action_mailer,
217
189
  :skip_test,
218
- :skip_sprockets,
219
190
  :skip_action_cable,
220
191
  :skip_active_job
221
192
  ),
@@ -262,6 +233,11 @@ module Rails
262
233
  options[:skip_dev_gems]
263
234
  end
264
235
 
236
+ def skip_sprockets?
237
+ options[:skip_asset_pipeline] || options[:asset_pipeline] != "sprockets"
238
+ end
239
+
240
+
265
241
  class GemfileEntry < Struct.new(:name, :version, :comment, :options, :commented_out)
266
242
  def initialize(name, version, comment, options = {}, commented_out = false)
267
243
  super
@@ -287,7 +263,7 @@ module Rails
287
263
  version = super
288
264
 
289
265
  if version.is_a?(Array)
290
- version.join("', '")
266
+ version.join('", "')
291
267
  else
292
268
  version
293
269
  end
@@ -297,20 +273,21 @@ module Rails
297
273
  def rails_gemfile_entry
298
274
  if options.dev?
299
275
  [
300
- GemfileEntry.path("rails", Rails::Generators::RAILS_DEV_PATH)
276
+ GemfileEntry.path("rails", Rails::Generators::RAILS_DEV_PATH, "Use local checkout of Rails")
301
277
  ]
302
278
  elsif options.edge?
279
+ edge_branch = Rails.gem_version.prerelease? ? "main" : [*Rails.gem_version.segments.first(2), "stable"].join("-")
303
280
  [
304
- GemfileEntry.github("rails", "rails/rails", "6-1-stable")
281
+ GemfileEntry.github("rails", "rails/rails", edge_branch, "Use specific branch of Rails")
305
282
  ]
306
- elsif options.master?
283
+ elsif options.main?
307
284
  [
308
- GemfileEntry.github("rails", "rails/rails", "main")
285
+ GemfileEntry.github("rails", "rails/rails", "main", "Use main development branch of Rails")
309
286
  ]
310
287
  else
311
288
  [GemfileEntry.version("rails",
312
289
  rails_version_specifier,
313
- "Bundle edge Rails instead: gem 'rails', github: 'rails/rails', branch: 'main'")]
290
+ %(Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"))]
314
291
  end
315
292
  end
316
293
 
@@ -327,30 +304,55 @@ module Rails
327
304
  end
328
305
  end
329
306
 
330
- def assets_gemfile_entry
331
- return [] if options[:skip_sprockets]
332
-
333
- GemfileEntry.version("sass-rails", ">= 6", "Use SCSS for stylesheets")
307
+ def jbuilder_gemfile_entry
308
+ return [] if options[:skip_jbuilder]
309
+ comment = "Build JSON APIs with ease [https://github.com/rails/jbuilder]"
310
+ GemfileEntry.new "jbuilder", "~> 2.11", comment, {}, options[:api]
334
311
  end
335
312
 
336
- def webpacker_gemfile_entry
313
+ def javascript_gemfile_entry
337
314
  return [] if options[:skip_javascript]
338
315
 
339
- GemfileEntry.version "webpacker", "~> 5.0", "Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker"
316
+ if adjusted_javascript_option == "importmap"
317
+ GemfileEntry.version("importmap-rails", ">= 0.9.2", "Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]")
318
+ else
319
+ GemfileEntry.version "jsbundling-rails", ">= 0.2.2", "Bundle and transpile JavaScript [https://github.com/rails/jsbundling-rails]"
320
+ end
340
321
  end
341
322
 
342
- def jbuilder_gemfile_entry
343
- return [] if options[:skip_jbuilder]
344
- comment = "Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder"
345
- GemfileEntry.new "jbuilder", "~> 2.7", comment, {}, options[:api]
323
+ def hotwire_gemfile_entry
324
+ return [] if options[:skip_javascript] || options[:skip_hotwire]
325
+
326
+ turbo_rails_entry =
327
+ GemfileEntry.version("turbo-rails", ">= 0.9.0", "Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]")
328
+
329
+ stimulus_rails_entry =
330
+ GemfileEntry.version("stimulus-rails", ">= 0.7.3", "Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]")
331
+
332
+ [ turbo_rails_entry, stimulus_rails_entry ]
346
333
  end
347
334
 
348
- def javascript_gemfile_entry
349
- if options[:skip_javascript] || options[:skip_turbolinks]
350
- []
335
+ def using_node?
336
+ options[:javascript] && options[:javascript] != "importmap"
337
+ end
338
+
339
+ # CSS processors other than Tailwind require a node-based JavaScript environment. So overwrite the normal JS default
340
+ # if one such processor has been specified.
341
+ def adjusted_javascript_option
342
+ if options[:css] && options[:css] != "tailwind" && options[:javascript] == "importmap"
343
+ "esbuild"
351
344
  else
352
- [ GemfileEntry.version("turbolinks", "~> 5",
353
- "Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks") ]
345
+ options[:javascript]
346
+ end
347
+ end
348
+
349
+ def css_gemfile_entry
350
+ return [] unless options[:css]
351
+
352
+ if !using_node? && options[:css] == "tailwind"
353
+ GemfileEntry.version("tailwindcss-rails", ">= 0.5.3", "Use Tailwind CSS [https://github.com/rails/tailwindcss-rails]")
354
+ else
355
+ GemfileEntry.version("cssbundling-rails", ">= 0.2.7", "Bundle and process CSS [https://github.com/rails/cssbundling-rails]")
354
356
  end
355
357
  end
356
358
 
@@ -397,51 +399,43 @@ module Rails
397
399
  end
398
400
 
399
401
  def bundle_install?
400
- !(options[:skip_gemfile] || options[:skip_bundle] || options[:pretend])
401
- end
402
-
403
- def spring_install?
404
- !options[:skip_spring] && !options.dev? && Process.respond_to?(:fork) && !RUBY_PLATFORM.include?("cygwin")
405
- end
406
-
407
- def webpack_install?
408
- !(options[:skip_javascript] || options[:skip_webpack_install])
402
+ !(options[:skip_bundle] || options[:pretend])
409
403
  end
410
404
 
411
405
  def depends_on_system_test?
412
406
  !(options[:skip_system_test] || options[:skip_test] || options[:api])
413
407
  end
414
408
 
415
- def depend_on_listen?
416
- !options[:skip_listen] && os_supports_listen_out_of_the_box?
417
- end
418
-
419
409
  def depend_on_bootsnap?
420
410
  !options[:skip_bootsnap] && !options[:dev] && !defined?(JRUBY_VERSION)
421
411
  end
422
412
 
423
- def os_supports_listen_out_of_the_box?
424
- /darwin|linux/.match?(RbConfig::CONFIG["host_os"])
425
- end
426
-
427
413
  def run_bundle
428
414
  bundle_command("install", "BUNDLE_IGNORE_MESSAGES" => "1") if bundle_install?
429
415
  end
430
416
 
431
- def run_webpack
432
- return unless webpack_install?
417
+ def run_javascript
418
+ return if options[:skip_javascript] || !bundle_install?
433
419
 
434
- unless bundle_install?
435
- say <<~EXPLAIN
436
- Skipping `rails webpacker:install` because `bundle install` was skipped.
437
- To complete setup, you must run `bundle install` followed by `rails webpacker:install`.
438
- EXPLAIN
439
- return
420
+ case adjusted_javascript_option
421
+ when "importmap" then rails_command "importmap:install"
422
+ when "webpack", "esbuild", "rollup" then rails_command "javascript:install:#{adjusted_javascript_option}"
440
423
  end
424
+ end
425
+
426
+ def run_hotwire
427
+ return if options[:skip_javascript] || options[:skip_hotwire] || !bundle_install?
428
+
429
+ rails_command "turbo:install stimulus:install"
430
+ end
431
+
432
+ def run_css
433
+ return if !options[:css] || !bundle_install?
441
434
 
442
- rails_command "webpacker:install"
443
- if options[:webpack] && options[:webpack] != "webpack"
444
- rails_command "webpacker:install:#{options[:webpack]}"
435
+ if !using_node? && options[:css] == "tailwind"
436
+ rails_command "tailwindcss:install"
437
+ else
438
+ rails_command "css:install:#{options[:css]}"
445
439
  end
446
440
  end
447
441
 
@@ -7,7 +7,7 @@ module Rails
7
7
 
8
8
  private
9
9
  def app_name
10
- @app_name ||= original_app_name.tr('\\', "").tr("-. ", "_")
10
+ @app_name ||= original_app_name.tr("\\", "").tr("-. ", "_")
11
11
  end
12
12
 
13
13
  def original_app_name
@@ -206,7 +206,7 @@ module Rails
206
206
  end
207
207
 
208
208
  # Make class option aware of Rails::Generators.options and Rails::Generators.aliases.
209
- def self.class_option(name, options = {}) #:nodoc:
209
+ def self.class_option(name, options = {}) # :nodoc:
210
210
  options[:desc] = "Indicates when to generate #{name.to_s.humanize.downcase}" unless options.key?(:desc)
211
211
  options[:aliases] = default_aliases_for_option(name, options)
212
212
  options[:default] = default_value_for_option(name, options)
@@ -231,7 +231,7 @@ module Rails
231
231
 
232
232
  # Cache source root and add lib/generators/base/generator/templates to
233
233
  # source paths.
234
- def self.inherited(base) #:nodoc:
234
+ def self.inherited(base) # :nodoc:
235
235
  super
236
236
 
237
237
  # Invoke source_root so the default_source_root is set.
@@ -324,21 +324,17 @@ module Rails
324
324
 
325
325
  # Sets the base_name taking into account the current class namespace.
326
326
  def self.base_name # :doc:
327
- @base_name ||= begin
328
- if base = name.to_s.split("::").first
329
- base.underscore
330
- end
327
+ @base_name ||= if base = name.to_s.split("::").first
328
+ base.underscore
331
329
  end
332
330
  end
333
331
 
334
332
  # Removes the namespaces and get the generator name. For example,
335
333
  # Rails::Generators::ModelGenerator will return "model" as generator name.
336
334
  def self.generator_name # :doc:
337
- @generator_name ||= begin
338
- if generator = name.to_s.split("::").last
339
- generator.delete_suffix!("Generator")
340
- generator.underscore
341
- end
335
+ @generator_name ||= if generator = name.to_s.split("::").last
336
+ generator.delete_suffix!("Generator")
337
+ generator.underscore
342
338
  end
343
339
  end
344
340
 
@@ -368,13 +364,13 @@ module Rails
368
364
  end
369
365
 
370
366
  # Keep hooks configuration that are used on prepare_for_invocation.
371
- def self.hooks #:nodoc:
367
+ def self.hooks # :nodoc:
372
368
  @hooks ||= from_superclass(:hooks, {})
373
369
  end
374
370
 
375
371
  # Prepare class invocation to search on Rails namespace if a previous
376
372
  # added hook is being used.
377
- def self.prepare_for_invocation(name, value) #:nodoc:
373
+ def self.prepare_for_invocation(name, value) # :nodoc:
378
374
  return super unless value.is_a?(String) || value.is_a?(Symbol)
379
375
 
380
376
  if value && constants = hooks[name]
@@ -21,6 +21,8 @@ module Erb # :nodoc:
21
21
  template filename, File.join("app/views", controller_file_path, filename)
22
22
  end
23
23
  end
24
+
25
+ template "partial.html.erb", File.join("app/views", controller_file_path, "_#{singular_name}.html.erb")
24
26
  end
25
27
 
26
28
  private
@@ -1,6 +1,6 @@
1
1
  <%%= form_with(model: <%= model_resource_name %>) do |form| %>
2
2
  <%% if <%= singular_table_name %>.errors.any? %>
3
- <div id="error_explanation">
3
+ <div style="color: red">
4
4
  <h2><%%= pluralize(<%= singular_table_name %>.errors.count, "error") %> prohibited this <%= singular_table_name %> from being saved:</h2>
5
5
 
6
6
  <ul>
@@ -12,26 +12,26 @@
12
12
  <%% end %>
13
13
 
14
14
  <% attributes.each do |attribute| -%>
15
- <div class="field">
15
+ <div>
16
16
  <% if attribute.password_digest? -%>
17
- <%%= form.label :password %>
17
+ <%%= form.label :password, style: "display: block" %>
18
18
  <%%= form.password_field :password %>
19
19
  </div>
20
20
 
21
- <div class="field">
22
- <%%= form.label :password_confirmation %>
21
+ <div>
22
+ <%%= form.label :password_confirmation, style: "display: block" %>
23
23
  <%%= form.password_field :password_confirmation %>
24
24
  <% elsif attribute.attachments? -%>
25
- <%%= form.label :<%= attribute.column_name %> %>
25
+ <%%= form.label :<%= attribute.column_name %>, style: "display: block" %>
26
26
  <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, multiple: true %>
27
27
  <% else -%>
28
- <%%= form.label :<%= attribute.column_name %> %>
28
+ <%%= form.label :<%= attribute.column_name %>, style: "display: block" %>
29
29
  <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %> %>
30
30
  <% end -%>
31
31
  </div>
32
32
 
33
33
  <% end -%>
34
- <div class="actions">
34
+ <div>
35
35
  <%%= form.submit %>
36
36
  </div>
37
37
  <%% end %>
@@ -1,6 +1,10 @@
1
- <h1>Editing <%= singular_table_name.titleize %></h1>
1
+ <h1>Editing <%= human_name.downcase %></h1>
2
2
 
3
- <%%= render 'form', <%= singular_table_name %>: @<%= singular_table_name %> %>
3
+ <%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
4
4
 
5
- <%%= link_to 'Show', @<%= singular_table_name %> %> |
6
- <%%= link_to 'Back', <%= index_helper %>_path %>
5
+ <br>
6
+
7
+ <div>
8
+ <%%= link_to "Show this <%= human_name.downcase %>", @<%= singular_table_name %> %> |
9
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper %>_path %>
10
+ </div>
@@ -1,31 +1,9 @@
1
- <p id="notice"><%%= notice %></p>
1
+ <p style="color: green"><%%= notice %></p>
2
2
 
3
- <h1><%= plural_table_name.titleize %></h1>
3
+ <h1><%= human_name.pluralize %></h1>
4
4
 
5
- <table>
6
- <thead>
7
- <tr>
8
- <% attributes.reject(&:password_digest?).each do |attribute| -%>
9
- <th><%= attribute.human_name %></th>
10
- <% end -%>
11
- <th colspan="3"></th>
12
- </tr>
13
- </thead>
5
+ <div id="<%= plural_table_name %>">
6
+ <%%= render @<%= plural_table_name %> %>
7
+ </div>
14
8
 
15
- <tbody>
16
- <%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
17
- <tr>
18
- <% attributes.reject(&:password_digest?).each do |attribute| -%>
19
- <td><%%= <%= singular_table_name %>.<%= attribute.column_name %> %></td>
20
- <% end -%>
21
- <td><%%= link_to 'Show', <%= model_resource_name %> %></td>
22
- <td><%%= link_to 'Edit', edit_<%= singular_route_name %>_path(<%= singular_table_name %>) %></td>
23
- <td><%%= link_to 'Destroy', <%= model_resource_name %>, method: :delete, data: { confirm: 'Are you sure?' } %></td>
24
- </tr>
25
- <%% end %>
26
- </tbody>
27
- </table>
28
-
29
- <br>
30
-
31
- <%%= link_to 'New <%= singular_table_name.titleize %>', new_<%= singular_route_name %>_path %>
9
+ <%%= link_to "New <%= human_name.downcase %>", new_<%= singular_route_name %>_path %>
@@ -1,5 +1,9 @@
1
- <h1>New <%= singular_table_name.titleize %></h1>
1
+ <h1>New <%= human_name.downcase %></h1>
2
2
 
3
- <%%= render 'form', <%= singular_table_name %>: @<%= singular_table_name %> %>
3
+ <%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
4
4
 
5
- <%%= link_to 'Back', <%= index_helper %>_path %>
5
+ <br>
6
+
7
+ <div>
8
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper %>_path %>
9
+ </div>
@@ -0,0 +1,20 @@
1
+ <div id="<%%= dom_id <%= singular_name %> %>">
2
+ <% attributes.reject(&:password_digest?).each do |attribute| -%>
3
+ <p>
4
+ <strong><%= attribute.human_name %>:</strong>
5
+ <% if attribute.attachment? -%>
6
+ <%%= link_to <%= singular_name %>.<%= attribute.column_name %>.filename, <%= singular_name %>.<%= attribute.column_name %> if <%= singular_name %>.<%= attribute.column_name %>.attached? %>
7
+ <% elsif attribute.attachments? -%>
8
+ <%% <%= singular_name %>.<%= attribute.column_name %>.each do |<%= attribute.singular_name %>| %>
9
+ <div><%%= link_to <%= attribute.singular_name %>.filename, <%= attribute.singular_name %> %></div>
10
+ <%% end %>
11
+ <% else -%>
12
+ <%%= <%= singular_name %>.<%= attribute.column_name %> %>
13
+ <% end -%>
14
+ </p>
15
+
16
+ <% end -%>
17
+ <p>
18
+ <%%= link_to "Show this <%= human_name.downcase %>", <%= singular_name %> %>
19
+ </p>
20
+ </div>
@@ -1,19 +1,10 @@
1
- <p id="notice"><%%= notice %></p>
1
+ <p style="color: green"><%%= notice %></p>
2
2
 
3
- <% attributes.reject(&:password_digest?).each do |attribute| -%>
4
- <p>
5
- <strong><%= attribute.human_name %>:</strong>
6
- <% if attribute.attachment? -%>
7
- <%%= link_to @<%= singular_table_name %>.<%= attribute.column_name %>.filename, @<%= singular_table_name %>.<%= attribute.column_name %> if @<%= singular_table_name %>.<%= attribute.column_name %>.attached? %>
8
- <% elsif attribute.attachments? -%>
9
- <%% @<%= singular_table_name %>.<%= attribute.column_name %>.each do |<%= attribute.singular_name %>| %>
10
- <div><%%= link_to <%= attribute.singular_name %>.filename, <%= attribute.singular_name %> %></div>
11
- <%% end %>
12
- <% else -%>
13
- <%%= @<%= singular_table_name %>.<%= attribute.column_name %> %>
14
- <% end -%>
15
- </p>
3
+ <%%= render @<%= singular_table_name %> %>
16
4
 
17
- <% end -%>
18
- <%%= link_to 'Edit', edit_<%= singular_table_name %>_path(@<%= singular_table_name %>) %> |
19
- <%%= link_to 'Back', <%= index_helper %>_path %>
5
+ <div>
6
+ <%%= link_to "Edit this <%= human_name.downcase %>", edit_<%= singular_table_name %>_path(@<%= singular_table_name %>) %> |
7
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper %>_path %>
8
+
9
+ <%%= button_to "Destroy this <%= human_name.downcase %>", <%= singular_table_name %>_path(@<%= singular_table_name %>), method: :delete %>
10
+ </div>
@@ -4,7 +4,7 @@ require "rails/generators/named_base"
4
4
 
5
5
  module Erb # :nodoc:
6
6
  module Generators # :nodoc:
7
- class Base < Rails::Generators::NamedBase #:nodoc:
7
+ class Base < Rails::Generators::NamedBase # :nodoc:
8
8
  private
9
9
  def formats
10
10
  [format]