railties 6.1.7.7 → 7.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +89 -458
  3. data/MIT-LICENSE +1 -1
  4. data/RDOC_MAIN.rdoc +16 -16
  5. data/README.rdoc +0 -1
  6. data/lib/rails/app_updater.rb +2 -4
  7. data/lib/rails/application/bootstrap.rb +17 -5
  8. data/lib/rails/application/configuration.rb +52 -31
  9. data/lib/rails/application/default_middleware_stack.rb +6 -3
  10. data/lib/rails/application/finisher.rb +43 -85
  11. data/lib/rails/application/routes_reloader.rb +8 -0
  12. data/lib/rails/application.rb +24 -50
  13. data/lib/rails/application_controller.rb +2 -2
  14. data/lib/rails/autoloaders/inflector.rb +21 -0
  15. data/lib/rails/autoloaders.rb +12 -16
  16. data/lib/rails/code_statistics.rb +2 -2
  17. data/lib/rails/code_statistics_calculator.rb +10 -1
  18. data/lib/rails/command/base.rb +26 -12
  19. data/lib/rails/command/behavior.rb +1 -1
  20. data/lib/rails/command/environment_argument.rb +1 -1
  21. data/lib/rails/command.rb +8 -5
  22. data/lib/rails/commands/credentials/USAGE +4 -2
  23. data/lib/rails/commands/credentials/credentials_command/diffing.rb +26 -16
  24. data/lib/rails/commands/credentials/credentials_command.rb +6 -2
  25. data/lib/rails/commands/dbconsole/dbconsole_command.rb +16 -15
  26. data/lib/rails/commands/help/USAGE +3 -2
  27. data/lib/rails/commands/runner/runner_command.rb +3 -2
  28. data/lib/rails/commands/server/server_command.rb +2 -5
  29. data/lib/rails/configuration.rb +18 -23
  30. data/lib/rails/engine/configuration.rb +2 -2
  31. data/lib/rails/engine.rb +23 -27
  32. data/lib/rails/gem_version.rb +4 -4
  33. data/lib/rails/generators/actions/create_migration.rb +2 -4
  34. data/lib/rails/generators/actions.rb +35 -13
  35. data/lib/rails/generators/app_base.rb +66 -102
  36. data/lib/rails/generators/app_name.rb +1 -1
  37. data/lib/rails/generators/base.rb +9 -13
  38. data/lib/rails/generators/erb/scaffold/scaffold_generator.rb +2 -0
  39. data/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt +8 -4
  40. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +5 -27
  41. data/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt +7 -3
  42. data/lib/rails/generators/erb/scaffold/templates/partial.html.erb.tt +20 -0
  43. data/lib/rails/generators/erb/scaffold/templates/show.html.erb.tt +7 -16
  44. data/lib/rails/generators/erb.rb +1 -1
  45. data/lib/rails/generators/generated_attribute.rb +40 -4
  46. data/lib/rails/generators/migration.rb +2 -6
  47. data/lib/rails/generators/model_helpers.rb +1 -1
  48. data/lib/rails/generators/named_base.rb +1 -1
  49. data/lib/rails/generators/rails/app/app_generator.rb +44 -88
  50. data/lib/rails/generators/rails/app/templates/Gemfile.tt +41 -52
  51. data/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css.tt +2 -2
  52. data/lib/rails/generators/rails/app/templates/app/mailers/application_mailer.rb.tt +2 -2
  53. data/lib/rails/generators/rails/app/templates/app/models/application_record.rb.tt +1 -1
  54. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +3 -10
  55. data/lib/rails/generators/rails/app/templates/bin/rails.tt +1 -4
  56. data/lib/rails/generators/rails/app/templates/bin/rake.tt +0 -3
  57. data/lib/rails/generators/rails/app/templates/bin/setup.tt +9 -14
  58. data/lib/rails/generators/rails/app/templates/config/boot.rb.tt +1 -1
  59. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +2 -2
  60. data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt +3 -3
  61. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +3 -3
  62. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +2 -2
  63. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +3 -3
  64. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +2 -2
  65. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +3 -3
  66. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +1 -1
  67. data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +5 -5
  68. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +2 -11
  69. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +9 -15
  70. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +2 -7
  71. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +1 -5
  72. data/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +0 -5
  73. data/lib/rails/generators/rails/app/templates/config/initializers/cors.rb.tt +2 -2
  74. data/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb.tt +4 -4
  75. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_0.rb.tt +85 -0
  76. data/lib/rails/generators/rails/app/templates/config/locales/en.yml +3 -3
  77. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +1 -1
  78. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +3 -0
  79. data/lib/rails/generators/rails/app/templates/config/storage.yml.tt +5 -5
  80. data/lib/rails/generators/rails/app/templates/db/seeds.rb.tt +2 -2
  81. data/lib/rails/generators/rails/app/templates/gitattributes.tt +0 -5
  82. data/lib/rails/generators/rails/app/templates/gitignore.tt +0 -1
  83. data/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt +1 -1
  84. data/lib/rails/generators/rails/controller/controller_generator.rb +1 -2
  85. data/lib/rails/generators/rails/controller/templates/controller.rb.tt +0 -4
  86. data/lib/rails/generators/rails/db/system/change/change_generator.rb +1 -1
  87. data/lib/rails/generators/rails/generator/templates/%file_name%_generator.rb.tt +1 -1
  88. data/lib/rails/generators/rails/plugin/plugin_generator.rb +40 -15
  89. data/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt +4 -2
  90. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +9 -9
  91. data/lib/rails/generators/rails/plugin/templates/README.md.tt +1 -1
  92. data/lib/rails/generators/rails/plugin/templates/app/mailers/%namespaced_name%/application_mailer.rb.tt +2 -2
  93. data/lib/rails/generators/rails/plugin/templates/app/models/%namespaced_name%/application_record.rb.tt +1 -1
  94. data/lib/rails/generators/rails/plugin/templates/app/views/layouts/%namespaced_name%/application.html.erb.tt +0 -3
  95. data/lib/rails/generators/rails/plugin/templates/bin/rails.tt +4 -4
  96. data/lib/rails/generators/rails/plugin/templates/gitignore.tt +0 -5
  97. data/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb.tt +2 -2
  98. data/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/version.rb.tt +1 -1
  99. data/lib/rails/generators/rails/plugin/templates/rails/boot.rb.tt +2 -2
  100. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +3 -3
  101. data/lib/rails/generators/rails/scaffold/scaffold_generator.rb +0 -19
  102. data/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt +1 -5
  103. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt +6 -10
  104. data/lib/rails/generators/resource_helpers.rb +2 -2
  105. data/lib/rails/generators/test_unit/generator/templates/generator_test.rb.tt +1 -1
  106. data/lib/rails/generators/test_unit/model/templates/fixtures.yml.tt +2 -2
  107. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +3 -3
  108. data/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt +5 -5
  109. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt +2 -2
  110. data/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt +3 -3
  111. data/lib/rails/generators/testing/behaviour.rb +1 -2
  112. data/lib/rails/generators.rb +9 -22
  113. data/lib/rails/info.rb +1 -1
  114. data/lib/rails/info_controller.rb +1 -3
  115. data/lib/rails/initializable.rb +1 -1
  116. data/lib/rails/mailers_controller.rb +2 -4
  117. data/lib/rails/rack/logger.rb +0 -1
  118. data/lib/rails/railtie/configuration.rb +1 -2
  119. data/lib/rails/railtie.rb +9 -9
  120. data/lib/rails/ruby_version_check.rb +3 -3
  121. data/lib/rails/secrets.rb +8 -10
  122. data/lib/rails/tasks/framework.rake +2 -8
  123. data/lib/rails/tasks/statistics.rake +3 -1
  124. data/lib/rails/tasks/tmp.rake +8 -1
  125. data/lib/rails/tasks/yarn.rake +5 -1
  126. data/lib/rails/tasks/zeitwerk.rake +2 -10
  127. data/lib/rails/templates/layouts/application.html.erb +15 -0
  128. data/lib/rails/templates/rails/mailers/email.html.erb +12 -10
  129. data/lib/rails/templates/rails/welcome/index.html.erb +3 -0
  130. data/lib/rails/test_unit/railtie.rb +0 -4
  131. data/lib/rails/test_unit/runner.rb +7 -5
  132. data/lib/rails/test_unit/testing.rake +4 -9
  133. data/lib/rails.rb +1 -0
  134. metadata +37 -39
  135. data/lib/rails/command/spellchecker.rb +0 -57
  136. data/lib/rails/generators/css/assets/assets_generator.rb +0 -15
  137. data/lib/rails/generators/css/assets/templates/stylesheet.css +0 -4
  138. data/lib/rails/generators/css/scaffold/scaffold_generator.rb +0 -18
  139. data/lib/rails/generators/rails/app/templates/app/javascript/channels/consumer.js +0 -6
  140. data/lib/rails/generators/rails/app/templates/app/javascript/channels/index.js +0 -5
  141. data/lib/rails/generators/rails/app/templates/app/javascript/packs/application.js.tt +0 -23
  142. data/lib/rails/generators/rails/app/templates/bin/spring.tt +0 -13
  143. data/lib/rails/generators/rails/app/templates/bin/yarn.tt +0 -16
  144. data/lib/rails/generators/rails/app/templates/config/initializers/application_controller_renderer.rb.tt +0 -8
  145. data/lib/rails/generators/rails/app/templates/config/initializers/cookies_serializer.rb.tt +0 -5
  146. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_1.rb.tt +0 -67
  147. data/lib/rails/generators/rails/app/templates/config/spring.rb.tt +0 -6
  148. data/lib/rails/generators/rails/app/templates/package.json.tt +0 -11
  149. data/lib/rails/generators/rails/assets/USAGE +0 -16
  150. data/lib/rails/generators/rails/assets/assets_generator.rb +0 -26
  151. data/lib/rails/generators/rails/assets/templates/stylesheet.css +0 -4
  152. 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,17 @@ 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
61
  class_option :skip_sprockets, type: :boolean, aliases: "-S", default: false,
68
62
  desc: "Skip Sprockets files"
69
63
 
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"
75
-
76
64
  class_option :skip_javascript, type: :boolean, aliases: "-J", default: name == "plugin",
77
65
  desc: "Skip JavaScript files"
78
66
 
79
- class_option :skip_turbolinks, type: :boolean, default: false,
80
- desc: "Skip turbolinks gem"
67
+ class_option :skip_hotwire, type: :boolean, default: false,
68
+ desc: "Skip Hotwire integration"
81
69
 
82
70
  class_option :skip_jbuilder, type: :boolean, default: false,
83
71
  desc: "Skip jbuilder gem"
@@ -97,7 +85,7 @@ module Rails
97
85
  class_option :edge, type: :boolean, default: false,
98
86
  desc: "Set up the #{name} with Gemfile pointing to Rails repository"
99
87
 
100
- class_option :master, type: :boolean, default: false,
88
+ class_option :main, type: :boolean, default: false, aliases: "--master",
101
89
  desc: "Set up the #{name} with Gemfile pointing to Rails repository main branch"
102
90
 
103
91
  class_option :rc, type: :string, default: nil,
@@ -110,47 +98,22 @@ module Rails
110
98
  desc: "Show this help message and quit"
111
99
  end
112
100
 
113
- def initialize(positional_argv, option_argv, *)
114
- @argv = [*positional_argv, *option_argv]
101
+ def initialize(*)
115
102
  @gem_filter = lambda { |gem| true }
116
- @extra_entries = []
117
103
  super
118
104
  end
119
105
 
120
106
  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
107
  def gemfile_entries # :doc:
138
108
  [rails_gemfile_entry,
139
109
  database_gemfile_entry,
140
110
  web_server_gemfile_entry,
141
- assets_gemfile_entry,
142
- webpacker_gemfile_entry,
143
111
  javascript_gemfile_entry,
112
+ hotwire_gemfile_entry,
113
+ css_gemfile_entry,
144
114
  jbuilder_gemfile_entry,
145
115
  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]
116
+ cable_gemfile_entry].flatten.find_all(&@gem_filter)
154
117
  end
155
118
 
156
119
  def builder # :doc:
@@ -173,14 +136,9 @@ module Rails
173
136
  end
174
137
 
175
138
  def apply_rails_template # :doc:
176
- original_argv = ARGV.dup
177
- ARGV.replace(@argv)
178
-
179
139
  apply rails_template if rails_template
180
140
  rescue Thor::Error, LoadError, Errno::ENOENT => e
181
141
  raise Error, "The template [#{rails_template}] could not be loaded. Error: #{e}"
182
- ensure
183
- ARGV.replace(original_argv)
184
142
  end
185
143
 
186
144
  def set_default_accessors! # :doc:
@@ -200,13 +158,11 @@ module Rails
200
158
  return [] if options[:skip_active_record]
201
159
  gem_name, gem_version = gem_for_database
202
160
  GemfileEntry.version gem_name, gem_version,
203
- "Use #{options[:database]} as the database for Active Record"
161
+ "Use #{options[:database]} as the database for Active Record"
204
162
  end
205
163
 
206
164
  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)
165
+ GemfileEntry.new "puma", "~> 5.0", "Use the Puma web server [https://github.com/puma/puma]"
210
166
  end
211
167
 
212
168
  def include_all_railties? # :doc:
@@ -287,7 +243,7 @@ module Rails
287
243
  version = super
288
244
 
289
245
  if version.is_a?(Array)
290
- version.join("', '")
246
+ version.join('", "')
291
247
  else
292
248
  version
293
249
  end
@@ -297,20 +253,21 @@ module Rails
297
253
  def rails_gemfile_entry
298
254
  if options.dev?
299
255
  [
300
- GemfileEntry.path("rails", Rails::Generators::RAILS_DEV_PATH)
256
+ GemfileEntry.path("rails", Rails::Generators::RAILS_DEV_PATH, "Use local checkout of Rails")
301
257
  ]
302
258
  elsif options.edge?
259
+ edge_branch = Rails.gem_version.prerelease? ? "main" : [*Rails.gem_version.segments.first(2), "stable"].join("-")
303
260
  [
304
- GemfileEntry.github("rails", "rails/rails", "6-1-stable")
261
+ GemfileEntry.github("rails", "rails/rails", edge_branch, "Use specific branch of Rails")
305
262
  ]
306
- elsif options.master?
263
+ elsif options.main?
307
264
  [
308
- GemfileEntry.github("rails", "rails/rails", "main")
265
+ GemfileEntry.github("rails", "rails/rails", "main", "Use main development branch of Rails")
309
266
  ]
310
267
  else
311
268
  [GemfileEntry.version("rails",
312
269
  rails_version_specifier,
313
- "Bundle edge Rails instead: gem 'rails', github: 'rails/rails', branch: 'main'")]
270
+ %(Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"))]
314
271
  end
315
272
  end
316
273
 
@@ -327,30 +284,45 @@ module Rails
327
284
  end
328
285
  end
329
286
 
330
- def assets_gemfile_entry
331
- return [] if options[:skip_sprockets]
332
-
333
- GemfileEntry.version("sass-rails", ">= 6", "Use SCSS for stylesheets")
287
+ def jbuilder_gemfile_entry
288
+ return [] if options[:skip_jbuilder]
289
+ comment = "Build JSON APIs with ease [https://github.com/rails/jbuilder]"
290
+ GemfileEntry.new "jbuilder", "~> 2.7", comment, {}, options[:api]
334
291
  end
335
292
 
336
- def webpacker_gemfile_entry
293
+ def javascript_gemfile_entry
337
294
  return [] if options[:skip_javascript]
338
295
 
339
- GemfileEntry.version "webpacker", "~> 5.0", "Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker"
296
+ if options[:javascript] == "importmap"
297
+ GemfileEntry.version("importmap-rails", ">= 0.3.4", "Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]")
298
+ else
299
+ GemfileEntry.version "jsbundling-rails", "~> 0.1.0", "Bundle and transpile JavaScript [https://github.com/rails/jsbundling-rails]"
300
+ end
340
301
  end
341
302
 
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]
303
+ def hotwire_gemfile_entry
304
+ return [] if options[:skip_javascript] || options[:skip_hotwire]
305
+
306
+ turbo_rails_entry =
307
+ GemfileEntry.version("turbo-rails", ">= 0.7.11", "Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]")
308
+
309
+ stimulus_rails_entry =
310
+ GemfileEntry.version("stimulus-rails", ">= 0.4.0", "Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]")
311
+
312
+ [ turbo_rails_entry, stimulus_rails_entry ]
346
313
  end
347
314
 
348
- def javascript_gemfile_entry
349
- if options[:skip_javascript] || options[:skip_turbolinks]
350
- []
315
+ def using_node?
316
+ options[:javascript] && options[:javascript] != "importmap"
317
+ end
318
+
319
+ def css_gemfile_entry
320
+ return [] unless options[:css]
321
+
322
+ if !using_node? && options[:css] == "tailwind"
323
+ GemfileEntry.version("tailwindcss-rails", ">= 0.4.3", "Use Tailwind CSS [https://github.com/rails/tailwindcss-rails]")
351
324
  else
352
- [ GemfileEntry.version("turbolinks", "~> 5",
353
- "Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks") ]
325
+ GemfileEntry.version("cssbundling-rails", ">= 0.1.0", "Bundle and process CSS [https://github.com/rails/cssbundling-rails]")
354
326
  end
355
327
  end
356
328
 
@@ -397,51 +369,43 @@ module Rails
397
369
  end
398
370
 
399
371
  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])
372
+ !(options[:skip_bundle] || options[:pretend])
409
373
  end
410
374
 
411
375
  def depends_on_system_test?
412
376
  !(options[:skip_system_test] || options[:skip_test] || options[:api])
413
377
  end
414
378
 
415
- def depend_on_listen?
416
- !options[:skip_listen] && os_supports_listen_out_of_the_box?
417
- end
418
-
419
379
  def depend_on_bootsnap?
420
380
  !options[:skip_bootsnap] && !options[:dev] && !defined?(JRUBY_VERSION)
421
381
  end
422
382
 
423
- def os_supports_listen_out_of_the_box?
424
- /darwin|linux/.match?(RbConfig::CONFIG["host_os"])
425
- end
426
-
427
383
  def run_bundle
428
384
  bundle_command("install", "BUNDLE_IGNORE_MESSAGES" => "1") if bundle_install?
429
385
  end
430
386
 
431
- def run_webpack
432
- return unless webpack_install?
387
+ def run_javascript
388
+ return if options[:skip_javascript] || !bundle_install?
433
389
 
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
390
+ case options[:javascript]
391
+ when "importmap" then rails_command "importmap:install"
392
+ when "webpack", "esbuild", "rollup" then rails_command "javascript:install:#{options[:javascript]}"
440
393
  end
394
+ end
441
395
 
442
- rails_command "webpacker:install"
443
- if options[:webpack] && options[:webpack] != "webpack"
444
- rails_command "webpacker:install:#{options[:webpack]}"
396
+ def run_hotwire
397
+ return if options[:skip_javascript] || options[:skip_hotwire] || !bundle_install?
398
+
399
+ rails_command "turbo:install stimulus:install"
400
+ end
401
+
402
+ def run_css
403
+ return if !options[:css] || !bundle_install?
404
+
405
+ if !using_node? && options[:css] == "tailwind"
406
+ rails_command "tailwindcss:install"
407
+ else
408
+ rails_command "css:install:#{options[:css]}"
445
409
  end
446
410
  end
447
411
 
@@ -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_table_name}.html.erb")
24
26
  end
25
27
 
26
28
  private
@@ -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
1
  <p id="notice"><%%= notice %></p>
2
2
 
3
- <h1><%= plural_table_name.titleize %></h1>
3
+ <h1><%= human_name %></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_table_name %> %>" class="scaffold_record">
2
+ <% attributes.reject(&:password_digest?).each do |attribute| -%>
3
+ <p>
4
+ <strong><%= attribute.human_name %>:</strong>
5
+ <% if attribute.attachment? -%>
6
+ <%%= link_to <%= singular_table_name %>.<%= attribute.column_name %>.filename, <%= singular_table_name %>.<%= attribute.column_name %> if <%= singular_table_name %>.<%= attribute.column_name %>.attached? %>
7
+ <% elsif attribute.attachments? -%>
8
+ <%% <%= singular_table_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_table_name %>.<%= attribute.column_name %> %>
13
+ <% end -%>
14
+ </p>
15
+
16
+ <% end -%>
17
+ <p>
18
+ <%%= link_to "Show this <%= human_name.downcase %>", <%= singular_table_name %> %>
19
+ </p>
20
+ </div>
@@ -1,19 +1,10 @@
1
1
  <p id="notice"><%%= 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]
@@ -7,6 +7,25 @@ module Rails
7
7
  class GeneratedAttribute # :nodoc:
8
8
  INDEX_OPTIONS = %w(index uniq)
9
9
  UNIQ_INDEX_OPTIONS = %w(uniq)
10
+ DEFAULT_TYPES = %w(
11
+ attachment
12
+ attachments
13
+ belongs_to
14
+ boolean
15
+ date
16
+ datetime
17
+ decimal
18
+ digest
19
+ float
20
+ integer
21
+ references
22
+ rich_text
23
+ string
24
+ text
25
+ time
26
+ timestamp
27
+ token
28
+ )
10
29
 
11
30
  attr_accessor :name, :type
12
31
  attr_reader :attr_options
@@ -14,23 +33,40 @@ module Rails
14
33
 
15
34
  class << self
16
35
  def parse(column_definition)
17
- name, type, has_index = column_definition.split(":")
36
+ name, type, index_type = column_definition.split(":")
18
37
 
19
38
  # if user provided "name:index" instead of "name:string:index"
20
39
  # type should be set blank so GeneratedAttribute's constructor
21
40
  # could set it to :string
22
- has_index, type = type, nil if INDEX_OPTIONS.include?(type)
41
+ index_type, type = type, nil if valid_index_type?(type)
23
42
 
24
43
  type, attr_options = *parse_type_and_options(type)
25
44
  type = type.to_sym if type
26
45
 
46
+ if type && !valid_type?(type)
47
+ raise Error, "Could not generate field '#{name}' with unknown type '#{type}'."
48
+ end
49
+
50
+ if index_type && !valid_index_type?(index_type)
51
+ raise Error, "Could not generate field '#{name}' with unknown index '#{index_type}'."
52
+ end
53
+
27
54
  if type && reference?(type)
28
- if UNIQ_INDEX_OPTIONS.include?(has_index)
55
+ if UNIQ_INDEX_OPTIONS.include?(index_type)
29
56
  attr_options[:index] = { unique: true }
30
57
  end
31
58
  end
32
59
 
33
- new(name, type, has_index, attr_options)
60
+ new(name, type, index_type, attr_options)
61
+ end
62
+
63
+ def valid_type?(type)
64
+ DEFAULT_TYPES.include?(type.to_s) ||
65
+ ActiveRecord::Base.connection.valid_type?(type)
66
+ end
67
+
68
+ def valid_index_type?(index_type)
69
+ INDEX_OPTIONS.include?(index_type.to_s)
34
70
  end
35
71
 
36
72
  def reference?(type)
@@ -12,7 +12,7 @@ module Rails
12
12
  extend ActiveSupport::Concern
13
13
  attr_reader :migration_number, :migration_file_name, :migration_class_name
14
14
 
15
- module ClassMethods #:nodoc:
15
+ module ClassMethods # :nodoc:
16
16
  def migration_lookup_at(dirname)
17
17
  Dir.glob("#{dirname}/[0-9]*_*.rb")
18
18
  end
@@ -63,11 +63,7 @@ module Rails
63
63
  numbered_destination = File.join(dir, ["%migration_number%", base].join("_"))
64
64
 
65
65
  file = create_migration numbered_destination, nil, config do
66
- if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+
67
- ERB.new(::File.binread(source), trim_mode: "-", eoutvar: "@output_buffer").result(context)
68
- else
69
- ERB.new(::File.binread(source), nil, "-", "@output_buffer").result(context)
70
- end
66
+ ERB.new(::File.binread(source), trim_mode: "-", eoutvar: "@output_buffer").result(context)
71
67
  end
72
68
  Rails::Generators.add_generated_file(file)
73
69
  end
@@ -18,7 +18,7 @@ module Rails
18
18
  ERROR
19
19
  mattr_accessor :skip_warn
20
20
 
21
- def self.included(base) #:nodoc:
21
+ def self.included(base) # :nodoc:
22
22
  base.class_option :force_plural, type: :boolean, default: false, desc: "Forces the use of the given model name"
23
23
  end
24
24
 
@@ -8,7 +8,7 @@ module Rails
8
8
  class NamedBase < Base
9
9
  argument :name, type: :string
10
10
 
11
- def initialize(args, *options) #:nodoc:
11
+ def initialize(args, *options) # :nodoc:
12
12
  @inside_template = nil
13
13
  # Unfreeze name in case it's given as a frozen string
14
14
  args[0] = args[0].dup if args[0].is_a?(String) && args[0].frozen?