railties 7.0.0.alpha2 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +46 -1
  3. data/lib/rails/all.rb +0 -1
  4. data/lib/rails/app_updater.rb +1 -1
  5. data/lib/rails/application/bootstrap.rb +6 -2
  6. data/lib/rails/application/configuration.rb +26 -9
  7. data/lib/rails/application/default_middleware_stack.rb +2 -1
  8. data/lib/rails/application/finisher.rb +2 -3
  9. data/lib/rails/commands/dbconsole/dbconsole_command.rb +0 -5
  10. data/lib/rails/engine/configuration.rb +1 -1
  11. data/lib/rails/engine.rb +3 -5
  12. data/lib/rails/gem_version.rb +1 -1
  13. data/lib/rails/generators/app_base.rb +88 -28
  14. data/lib/rails/generators/erb/scaffold/scaffold_generator.rb +1 -1
  15. data/lib/rails/generators/erb/scaffold/templates/_form.html.erb.tt +8 -8
  16. data/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt +2 -2
  17. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +9 -4
  18. data/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt +1 -1
  19. data/lib/rails/generators/erb/scaffold/templates/partial.html.erb.tt +4 -7
  20. data/lib/rails/generators/erb/scaffold/templates/show.html.erb.tt +4 -4
  21. data/lib/rails/generators/generated_attribute.rb +5 -5
  22. data/lib/rails/generators/named_base.rb +10 -10
  23. data/lib/rails/generators/rails/app/app_generator.rb +13 -6
  24. data/lib/rails/generators/rails/app/templates/Gemfile.tt +21 -20
  25. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +1 -0
  26. data/lib/rails/generators/rails/app/templates/config/application.rb.tt +0 -1
  27. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +4 -1
  28. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +2 -23
  29. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +4 -4
  30. data/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +19 -20
  31. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_0.rb.tt +36 -4
  32. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +2 -2
  33. data/lib/rails/generators/rails/app/templates/gitignore.tt +3 -0
  34. data/lib/rails/generators/rails/plugin/plugin_generator.rb +9 -17
  35. data/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt +4 -2
  36. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +5 -14
  37. data/lib/rails/generators/rails/plugin/templates/app/models/%namespaced_name%/application_record.rb.tt +1 -1
  38. data/lib/rails/generators/rails/plugin/templates/bin/rails.tt +0 -1
  39. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +0 -5
  40. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt +5 -5
  41. data/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt +7 -9
  42. data/lib/rails/generators/testing/behaviour.rb +2 -2
  43. data/lib/rails/railtie.rb +18 -1
  44. data/lib/rails/tasks/yarn.rake +4 -9
  45. data/lib/rails/templates/rails/mailers/email.html.erb +1 -1
  46. data/lib/rails/templates/rails/welcome/index.html.erb +60 -48
  47. data/lib/rails/test_unit/runner.rb +9 -4
  48. data/lib/rails/welcome_controller.rb +1 -0
  49. data/lib/rails.rb +4 -0
  50. metadata +19 -21
  51. data/lib/rails/generators/rails/app/templates/config/initializers/backtrace_silencers.rb.tt +0 -8
  52. data/lib/rails/generators/rails/app/templates/config/initializers/mime_types.rb.tt +0 -4
  53. data/lib/rails/generators/rails/app/templates/config/initializers/wrap_parameters.rb.tt +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b8e0ad6e3f3a0fb64531451d78166c6cede2e31642aa4322dba9b5b51440581f
4
- data.tar.gz: ff60ae45c8d2b5a202467bdf7ac92d94777ebf4d4affc828f6ed298c5c500174
3
+ metadata.gz: 5cb58ddc9e6fbbf28a0fb9c625cecec9cd282d59ccd697cf37cd1f78f7d25811
4
+ data.tar.gz: b6304f9dfa982671da582fb01c63f310b76d3d043aca2826ff5c54acecc7f90c
5
5
  SHA512:
6
- metadata.gz: 8986eb318c513e4aa6d31bec6c07d79b00eea61f6d086075a9aacbc1962f5127879c66243ed3536afa9303c6814b02cbdddb5b2f138c5365c0bba1443d59e185
7
- data.tar.gz: 81c23544a3a77276b33eef9a41b2f8404adefc98988f0527d60f02b1e8638e8d5eec4b86c3de594aaf76f96679d1e2efc18ad38a4f8a0fa1d08b037014f81e68
6
+ metadata.gz: febb1c2b1fc87226219dc2cf5870c236b801624c9a4d8c62b0853a1e3e033fbfec76e5b418de34774e069aa0b60d8b2c687c68ab729cc7165806974f16373b40
7
+ data.tar.gz: a6305f03e1ed58b3afd6a9647b6fb43a48007c08370db1e066c15e135ce159c9adc7ac84c318033264e1c18cafdf2d9446d3e08341e4922c46fb7c7b83a81ff7
data/CHANGELOG.md CHANGED
@@ -1,3 +1,48 @@
1
+ ## Rails 7.0.0 (December 15, 2021) ##
2
+
3
+ * No changes.
4
+
5
+
6
+ ## Rails 7.0.0.rc3 (December 14, 2021) ##
7
+
8
+ * Allow localhost with a port by default in development
9
+
10
+ [Fixes: #43864]
11
+
12
+ ## Rails 7.0.0.rc2 (December 14, 2021) ##
13
+
14
+ * No changes
15
+
16
+ ## Rails 7.0.0.rc1 (December 06, 2021) ##
17
+
18
+ * Remove deprecated `config` in `dbconsole`.
19
+
20
+ *Rafael Mendonça França*
21
+
22
+ * Change default `X-XSS-Protection` header to disable XSS auditor
23
+
24
+ This header has been deprecated and the XSS auditor it triggered
25
+ has been removed from all major modern browsers (in favour of
26
+ Content Security Policy) that implemented this header to begin with
27
+ (Firefox never did).
28
+
29
+ [OWASP](https://owasp.org/www-project-secure-headers/#x-xss-protection)
30
+ suggests setting this header to '0' to disable the default behaviour
31
+ on old browsers as it can introduce additional security issues.
32
+
33
+ Added the new behaviour as a framework default from Rails 7.0.
34
+
35
+ *Christian Sutter*
36
+
37
+ * Scaffolds now use date_field, time_field and datetime_field instead of
38
+ date_select, time_select and datetime_select; thus providing native date/time pickers.
39
+
40
+ *Martijn Lafeber*
41
+
42
+ * Fix a regression in which autoload paths were initialized too late.
43
+
44
+ *Xavier Noria*
45
+
1
46
  ## Rails 7.0.0.alpha2 (September 15, 2021) ##
2
47
 
3
48
  * Fix activestorage dependency in the npm package.
@@ -10,7 +55,7 @@
10
55
  or `config/initializers/cookies_serializer.rb`
11
56
 
12
57
  The default value for `cookies_serializer` (`:json`) has been moved to `config.load_defaults("7.0")`.
13
- The new framework defaults file sets the serializer to `:marshal`.
58
+ The new framework defaults file can be used to upgrade the serializer.
14
59
 
15
60
  *Alex Ghiculescu*
16
61
 
data/lib/rails/all.rb CHANGED
@@ -15,7 +15,6 @@ require "rails"
15
15
  action_mailbox/engine
16
16
  action_text/engine
17
17
  rails/test_unit/railtie
18
- sprockets/railtie
19
18
  ).each do |railtie|
20
19
  begin
21
20
  require railtie
@@ -25,7 +25,7 @@ module Rails
25
25
  options[:skip_active_storage] = !defined?(ActiveStorage::Engine) || !defined?(ActiveRecord::Railtie)
26
26
  options[:skip_action_mailer] = !defined?(ActionMailer::Railtie)
27
27
  options[:skip_action_cable] = !defined?(ActionCable::Engine)
28
- options[:skip_sprockets] = !defined?(Sprockets::Railtie)
28
+ options[:skip_asset_pipeline] = !defined?(Sprockets::Railtie) && !defined?(Propshaft::Railtie)
29
29
  options[:skip_bootsnap] = !defined?(Bootsnap)
30
30
  options[:updating] = true
31
31
  options
@@ -14,6 +14,7 @@ module Rails
14
14
  initializer :load_environment_hook, group: :all do end
15
15
 
16
16
  initializer :load_active_support, group: :all do
17
+ ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"] = "true" if config.active_support.disable_to_s_conversion
17
18
  require "active_support/all" unless config.active_support.bare
18
19
  end
19
20
 
@@ -49,8 +50,11 @@ module Rails
49
50
  )
50
51
  logger
51
52
  end
52
-
53
53
  Rails.logger.level = ActiveSupport::Logger.const_get(config.log_level.to_s.upcase)
54
+
55
+ unless config.consider_all_requests_local
56
+ Rails.error.logger = Rails.logger
57
+ end
54
58
  end
55
59
 
56
60
  # Initialize cache early in the stack so railties can make use of it.
@@ -66,7 +70,7 @@ module Rails
66
70
 
67
71
  # We setup the once autoloader this early so that engines and applications
68
72
  # are able to autoload from these paths during initialization.
69
- initializer :setup_once_autoloader do
73
+ initializer :setup_once_autoloader, after: :set_eager_load_paths, before: :bootstrap_hook do
70
74
  autoloader = Rails.autoloaders.once
71
75
 
72
76
  ActiveSupport::Dependencies.autoload_once_paths.freeze
@@ -21,7 +21,7 @@ module Rails
21
21
  :read_encrypted_secrets, :log_level, :content_security_policy_report_only,
22
22
  :content_security_policy_nonce_generator, :content_security_policy_nonce_directives,
23
23
  :require_master_key, :credentials, :disable_sandbox, :add_autoload_paths_to_load_path,
24
- :rake_eager_load
24
+ :rake_eager_load, :server_timing
25
25
 
26
26
  attr_reader :encoding, :api_only, :loaded_config_version
27
27
 
@@ -33,8 +33,12 @@ module Rails
33
33
  @filter_parameters = []
34
34
  @filter_redirect = []
35
35
  @helpers_paths = []
36
- @hosts = Array(([".localhost", IPAddr.new("0.0.0.0/0"), IPAddr.new("::/0")] if Rails.env.development?))
37
- @hosts.concat(ENV["RAILS_DEVELOPMENT_HOSTS"].to_s.split(",").map(&:strip)) if Rails.env.development?
36
+ if Rails.env.development?
37
+ @hosts = ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT +
38
+ ENV["RAILS_DEVELOPMENT_HOSTS"].to_s.split(",").map(&:strip)
39
+ else
40
+ @hosts = []
41
+ end
38
42
  @host_authorization = {}
39
43
  @public_file_server = ActiveSupport::OrderedOptions.new
40
44
  @public_file_server.enabled = true
@@ -74,6 +78,7 @@ module Rails
74
78
  @add_autoload_paths_to_load_path = true
75
79
  @permissions_policy = nil
76
80
  @rake_eager_load = false
81
+ @server_timing = false
77
82
  end
78
83
 
79
84
  # Loads default configurations. See {the result of the method for each version}[https://guides.rubyonrails.org/configuring.html#results-of-config-load-defaults].
@@ -83,6 +88,7 @@ module Rails
83
88
  if respond_to?(:action_controller)
84
89
  action_controller.per_form_csrf_tokens = true
85
90
  action_controller.forgery_protection_origin_check = true
91
+ action_controller.urlsafe_csrf_tokens = false
86
92
  end
87
93
 
88
94
  ActiveSupport.to_time_preserves_timezone = true
@@ -160,7 +166,6 @@ module Rails
160
166
 
161
167
  if respond_to?(:active_job)
162
168
  active_job.retry_jitter = 0.15
163
- active_job.skip_after_callbacks_if_terminated = true
164
169
  end
165
170
 
166
171
  if respond_to?(:action_dispatch)
@@ -169,7 +174,7 @@ module Rails
169
174
  end
170
175
 
171
176
  if respond_to?(:action_controller)
172
- action_controller.urlsafe_csrf_tokens = true
177
+ action_controller.delete(:urlsafe_csrf_tokens)
173
178
  end
174
179
 
175
180
  if respond_to?(:action_view)
@@ -198,14 +203,18 @@ module Rails
198
203
  load_defaults "6.1"
199
204
 
200
205
  if respond_to?(:action_dispatch)
206
+ action_dispatch.default_headers = {
207
+ "X-Frame-Options" => "SAMEORIGIN",
208
+ "X-XSS-Protection" => "0",
209
+ "X-Content-Type-Options" => "nosniff",
210
+ "X-Download-Options" => "noopen",
211
+ "X-Permitted-Cross-Domain-Policies" => "none",
212
+ "Referrer-Policy" => "strict-origin-when-cross-origin"
213
+ }
201
214
  action_dispatch.return_only_request_media_type_on_content_type = false
202
215
  action_dispatch.cookies_serializer = :json
203
216
  end
204
217
 
205
- if respond_to?(:action_controller)
206
- action_controller.silence_disabled_session_errors = false
207
- end
208
-
209
218
  if respond_to?(:action_view)
210
219
  action_view.button_to_generates_button_tag = true
211
220
  action_view.apply_stylesheet_media_default = false
@@ -216,6 +225,10 @@ module Rails
216
225
  active_support.key_generator_hash_digest_class = OpenSSL::Digest::SHA256
217
226
  active_support.remove_deprecated_time_with_zone_name = true
218
227
  active_support.cache_format_version = 7.0
228
+ active_support.use_rfc4122_namespaced_uuids = true
229
+ active_support.executor_around_test_case = true
230
+ active_support.isolation_level = :thread
231
+ active_support.disable_to_s_conversion = true
219
232
  end
220
233
 
221
234
  if respond_to?(:action_mailer)
@@ -228,15 +241,19 @@ module Rails
228
241
  " -frames:v 1 -f image2"
229
242
 
230
243
  active_storage.variant_processor = :vips
244
+ active_storage.multiple_file_field_include_hidden = true
231
245
  end
232
246
 
233
247
  if respond_to?(:active_record)
234
248
  active_record.verify_foreign_keys_for_fixtures = true
235
249
  active_record.partial_inserts = false
250
+ active_record.automatic_scope_inversing = true
236
251
  end
237
252
 
238
253
  if respond_to?(:action_controller)
239
254
  action_controller.raise_on_open_redirects = true
255
+
256
+ action_controller.wrap_parameters_by_default = true
240
257
  end
241
258
  else
242
259
  raise "Unknown version #{target_version.to_s.inspect}"
@@ -13,7 +13,7 @@ module Rails
13
13
 
14
14
  def build_stack
15
15
  ActionDispatch::MiddlewareStack.new do |middleware|
16
- middleware.use ::ActionDispatch::HostAuthorization, config.hosts, config.action_dispatch.hosts_response_app, **config.host_authorization
16
+ middleware.use ::ActionDispatch::HostAuthorization, config.hosts, **config.host_authorization
17
17
 
18
18
  if config.force_ssl
19
19
  middleware.use ::ActionDispatch::SSL, **config.ssl_options,
@@ -42,6 +42,7 @@ module Rails
42
42
 
43
43
  middleware.use ::ActionDispatch::Executor, app.executor
44
44
 
45
+ middleware.use ::ActionDispatch::ServerTiming if config.server_timing
45
46
  middleware.use ::Rack::Runtime
46
47
  middleware.use ::Rack::MethodOverride unless config.api_only
47
48
  middleware.use ::ActionDispatch::RequestId, header: config.action_dispatch.request_id_header
@@ -176,9 +176,7 @@ module Rails
176
176
  initializer :set_clear_dependencies_hook, group: :all do |app|
177
177
  callback = lambda do
178
178
  # Order matters.
179
- ActiveSupport::DescendantsTracker.clear(
180
- only: ActiveSupport::Dependencies._autoloaded_tracked_classes
181
- )
179
+ ActiveSupport::DescendantsTracker.clear(ActiveSupport::Dependencies._autoloaded_tracked_classes)
182
180
  ActiveSupport::Dependencies.clear
183
181
  end
184
182
 
@@ -194,6 +192,7 @@ module Rails
194
192
 
195
193
  if config.cache_classes
196
194
  # No reloader
195
+ ActiveSupport::DescendantsTracker.disable_clear!
197
196
  elsif config.reload_classes_only_on_change
198
197
  reloader = config.file_watcher.new(*watchable_args, &callback)
199
198
  reloaders << reloader
@@ -94,11 +94,6 @@ module Rails
94
94
  end
95
95
  end
96
96
 
97
- def config
98
- db_config.configuration_hash
99
- end
100
- deprecate config: "please use db_config.configuration_hash"
101
-
102
97
  def db_config
103
98
  return @db_config if defined?(@db_config)
104
99
 
@@ -44,7 +44,7 @@ module Rails
44
44
  exclude: ["assets", javascript_path]
45
45
  paths.add "app/assets", glob: "*"
46
46
  paths.add "app/controllers", eager_load: true
47
- paths.add "app/channels", eager_load: true, glob: "**/*_channel.rb"
47
+ paths.add "app/channels", eager_load: true
48
48
  paths.add "app/helpers", eager_load: true
49
49
  paths.add "app/models", eager_load: true
50
50
  paths.add "app/mailers", eager_load: true
data/lib/rails/engine.rb CHANGED
@@ -570,14 +570,12 @@ module Rails
570
570
  $LOAD_PATH.uniq!
571
571
  end
572
572
 
573
- initializer :set_autoload_once_paths, before: :setup_once_autoloader do
574
- config.autoload_once_paths.freeze
573
+ initializer :set_autoload_paths, before: :bootstrap_hook do
574
+ ActiveSupport::Dependencies.autoload_paths.unshift(*_all_autoload_paths)
575
575
  ActiveSupport::Dependencies.autoload_once_paths.unshift(*_all_autoload_once_paths)
576
- end
577
576
 
578
- initializer :set_autoload_paths, before: :setup_main_autoloader do
579
577
  config.autoload_paths.freeze
580
- ActiveSupport::Dependencies.autoload_paths.unshift(*_all_autoload_paths)
578
+ config.autoload_once_paths.freeze
581
579
  end
582
580
 
583
581
  initializer :set_eager_load_paths, before: :bootstrap_hook do
@@ -10,7 +10,7 @@ module Rails
10
10
  MAJOR = 7
11
11
  MINOR = 0
12
12
  TINY = 0
13
- PRE = "alpha2"
13
+ PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -58,8 +58,10 @@ module Rails
58
58
  class_option :skip_action_cable, type: :boolean, aliases: "-C", default: false,
59
59
  desc: "Skip Action Cable files"
60
60
 
61
- class_option :skip_sprockets, type: :boolean, aliases: "-S", default: false,
62
- desc: "Skip Sprockets files"
61
+ class_option :skip_asset_pipeline, type: :boolean, aliases: "-A", default: false
62
+
63
+ class_option :asset_pipeline, type: :string, aliases: "-a", default: "sprockets",
64
+ desc: "Choose your asset pipeline [options: sprockets (default), propshaft]"
63
65
 
64
66
  class_option :skip_javascript, type: :boolean, aliases: "-J", default: name == "plugin",
65
67
  desc: "Skip JavaScript files"
@@ -98,7 +100,8 @@ module Rails
98
100
  desc: "Show this help message and quit"
99
101
  end
100
102
 
101
- def initialize(*)
103
+ def initialize(positional_argv, option_argv, *)
104
+ @argv = [*positional_argv, *option_argv]
102
105
  @gem_filter = lambda { |gem| true }
103
106
  super
104
107
  end
@@ -106,6 +109,7 @@ module Rails
106
109
  private
107
110
  def gemfile_entries # :doc:
108
111
  [rails_gemfile_entry,
112
+ asset_pipeline_gemfile_entry,
109
113
  database_gemfile_entry,
110
114
  web_server_gemfile_entry,
111
115
  javascript_gemfile_entry,
@@ -148,7 +152,7 @@ module Rails
148
152
  when /^https?:\/\//
149
153
  options[:template]
150
154
  when String
151
- File.expand_path(options[:template], Dir.pwd)
155
+ File.expand_path(`echo #{options[:template]}`.strip)
152
156
  else
153
157
  options[:template]
154
158
  end
@@ -165,13 +169,25 @@ module Rails
165
169
  GemfileEntry.new "puma", "~> 5.0", "Use the Puma web server [https://github.com/puma/puma]"
166
170
  end
167
171
 
172
+ def asset_pipeline_gemfile_entry
173
+ return [] if options[:skip_asset_pipeline]
174
+
175
+ if options[:asset_pipeline] == "sprockets"
176
+ GemfileEntry.floats "sprockets-rails",
177
+ "The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]"
178
+ elsif options[:asset_pipeline] == "propshaft"
179
+ GemfileEntry.floats "propshaft", "The modern asset pipeline for Rails [https://github.com/rails/propshaft]"
180
+ else
181
+ []
182
+ end
183
+ end
184
+
168
185
  def include_all_railties? # :doc:
169
186
  [
170
187
  options.values_at(
171
188
  :skip_active_record,
172
189
  :skip_action_mailer,
173
190
  :skip_test,
174
- :skip_sprockets,
175
191
  :skip_action_cable,
176
192
  :skip_active_job
177
193
  ),
@@ -218,6 +234,11 @@ module Rails
218
234
  options[:skip_dev_gems]
219
235
  end
220
236
 
237
+ def skip_sprockets?
238
+ options[:skip_asset_pipeline] || options[:asset_pipeline] != "sprockets"
239
+ end
240
+
241
+
221
242
  class GemfileEntry < Struct.new(:name, :version, :comment, :options, :commented_out)
222
243
  def initialize(name, version, comment, options = {}, commented_out = false)
223
244
  super
@@ -235,6 +256,10 @@ module Rails
235
256
  new(name, version, comment)
236
257
  end
237
258
 
259
+ def self.floats(name, comment = nil)
260
+ new(name, nil, comment)
261
+ end
262
+
238
263
  def self.path(name, path, comment = nil)
239
264
  new(name, nil, comment, path: path)
240
265
  end
@@ -248,26 +273,30 @@ module Rails
248
273
  version
249
274
  end
250
275
  end
276
+
277
+ def to_s
278
+ [ ("# #{comment}\n" if comment),
279
+ ("# " if commented_out), "gem \"#{name}\"", (", \"#{version}\"" if version),
280
+ *options.map { |key, val| ", #{key}: #{val.inspect}" }
281
+ ].compact.join
282
+ end
283
+ end
284
+
285
+ def rails_prerelease?
286
+ options.dev? || options.edge? || options.main?
251
287
  end
252
288
 
253
289
  def rails_gemfile_entry
254
290
  if options.dev?
255
- [
256
- GemfileEntry.path("rails", Rails::Generators::RAILS_DEV_PATH, "Use local checkout of Rails")
257
- ]
291
+ GemfileEntry.path("rails", Rails::Generators::RAILS_DEV_PATH, "Use local checkout of Rails")
258
292
  elsif options.edge?
259
293
  edge_branch = Rails.gem_version.prerelease? ? "main" : [*Rails.gem_version.segments.first(2), "stable"].join("-")
260
- [
261
- GemfileEntry.github("rails", "rails/rails", edge_branch, "Use specific branch of Rails")
262
- ]
294
+ GemfileEntry.github("rails", "rails/rails", edge_branch, "Use specific branch of Rails")
263
295
  elsif options.main?
264
- [
265
- GemfileEntry.github("rails", "rails/rails", "main", "Use main development branch of Rails")
266
- ]
296
+ GemfileEntry.github("rails", "rails/rails", "main", "Use main development branch of Rails")
267
297
  else
268
- [GemfileEntry.version("rails",
269
- rails_version_specifier,
270
- %(Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"))]
298
+ GemfileEntry.version("rails", rails_version_specifier,
299
+ %(Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"))
271
300
  end
272
301
  end
273
302
 
@@ -286,17 +315,16 @@ module Rails
286
315
 
287
316
  def jbuilder_gemfile_entry
288
317
  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]
318
+ GemfileEntry.new "jbuilder", nil, "Build JSON APIs with ease [https://github.com/rails/jbuilder]", {}, options[:api]
291
319
  end
292
320
 
293
321
  def javascript_gemfile_entry
294
322
  return [] if options[:skip_javascript]
295
323
 
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]")
324
+ if adjusted_javascript_option == "importmap"
325
+ GemfileEntry.floats "importmap-rails", "Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]"
298
326
  else
299
- GemfileEntry.version "jsbundling-rails", "~> 0.1.0", "Bundle and transpile JavaScript [https://github.com/rails/jsbundling-rails]"
327
+ GemfileEntry.floats "jsbundling-rails", "Bundle and transpile JavaScript [https://github.com/rails/jsbundling-rails]"
300
328
  end
301
329
  end
302
330
 
@@ -304,10 +332,10 @@ module Rails
304
332
  return [] if options[:skip_javascript] || options[:skip_hotwire]
305
333
 
306
334
  turbo_rails_entry =
307
- GemfileEntry.version("turbo-rails", ">= 0.7.11", "Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]")
335
+ GemfileEntry.floats "turbo-rails", "Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]"
308
336
 
309
337
  stimulus_rails_entry =
310
- GemfileEntry.version("stimulus-rails", ">= 0.4.0", "Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]")
338
+ GemfileEntry.floats "stimulus-rails", "Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]"
311
339
 
312
340
  [ turbo_rails_entry, stimulus_rails_entry ]
313
341
  end
@@ -316,13 +344,23 @@ module Rails
316
344
  options[:javascript] && options[:javascript] != "importmap"
317
345
  end
318
346
 
347
+ # CSS processors other than Tailwind require a node-based JavaScript environment. So overwrite the normal JS default
348
+ # if one such processor has been specified.
349
+ def adjusted_javascript_option
350
+ if options[:css] && options[:css] != "tailwind" && options[:javascript] == "importmap"
351
+ "esbuild"
352
+ else
353
+ options[:javascript]
354
+ end
355
+ end
356
+
319
357
  def css_gemfile_entry
320
358
  return [] unless options[:css]
321
359
 
322
360
  if !using_node? && options[:css] == "tailwind"
323
- GemfileEntry.version("tailwindcss-rails", ">= 0.4.3", "Use Tailwind CSS [https://github.com/rails/tailwindcss-rails]")
361
+ GemfileEntry.floats "tailwindcss-rails", "Use Tailwind CSS [https://github.com/rails/tailwindcss-rails]"
324
362
  else
325
- GemfileEntry.version("cssbundling-rails", ">= 0.1.0", "Bundle and process CSS [https://github.com/rails/cssbundling-rails]")
363
+ GemfileEntry.floats "cssbundling-rails", "Bundle and process CSS [https://github.com/rails/cssbundling-rails]"
326
364
  end
327
365
  end
328
366
 
@@ -380,6 +418,28 @@ module Rails
380
418
  !options[:skip_bootsnap] && !options[:dev] && !defined?(JRUBY_VERSION)
381
419
  end
382
420
 
421
+ def target_rails_prerelease(self_command = "new")
422
+ return unless rails_prerelease? && bundle_install?
423
+
424
+ if !File.exist?(File.expand_path("Gemfile", destination_root))
425
+ create_file("Gemfile", <<~GEMFILE)
426
+ source "https://rubygems.org"
427
+ git_source(:github) { |repo| "https://github.com/\#{repo}.git" }
428
+ #{rails_gemfile_entry}
429
+ GEMFILE
430
+
431
+ run_bundle
432
+
433
+ @argv[0] = destination_root
434
+ require "shellwords"
435
+ bundle_command("exec rails #{self_command} #{Shellwords.join(@argv)}")
436
+ exit
437
+ else
438
+ remove_file("Gemfile")
439
+ remove_file("Gemfile.lock")
440
+ end
441
+ end
442
+
383
443
  def run_bundle
384
444
  bundle_command("install", "BUNDLE_IGNORE_MESSAGES" => "1") if bundle_install?
385
445
  end
@@ -387,9 +447,9 @@ module Rails
387
447
  def run_javascript
388
448
  return if options[:skip_javascript] || !bundle_install?
389
449
 
390
- case options[:javascript]
450
+ case adjusted_javascript_option
391
451
  when "importmap" then rails_command "importmap:install"
392
- when "webpack", "esbuild", "rollup" then rails_command "javascript:install:#{options[:javascript]}"
452
+ when "webpack", "esbuild", "rollup" then rails_command "javascript:install:#{adjusted_javascript_option}"
393
453
  end
394
454
  end
395
455
 
@@ -22,7 +22,7 @@ module Erb # :nodoc:
22
22
  end
23
23
  end
24
24
 
25
- template "partial.html.erb", File.join("app/views", controller_file_path, "_#{singular_table_name}.html.erb")
25
+ template "partial.html.erb", File.join("app/views", controller_file_path, "_#{singular_name}.html.erb")
26
26
  end
27
27
 
28
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 %>
@@ -5,6 +5,6 @@
5
5
  <br>
6
6
 
7
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 %>
8
+ <%%= link_to "Show this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %> %> |
9
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %> %>
10
10
  </div>
@@ -1,9 +1,14 @@
1
- <p id="notice"><%%= notice %></p>
1
+ <p style="color: green"><%%= notice %></p>
2
2
 
3
- <h1><%= human_name %></h1>
3
+ <h1><%= human_name.pluralize %></h1>
4
4
 
5
5
  <div id="<%= plural_table_name %>">
6
- <%%= render @<%= plural_table_name %> %>
6
+ <%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
7
+ <%%= render <%= singular_table_name %> %>
8
+ <p>
9
+ <%%= link_to "Show this <%= human_name.downcase %>", <%= model_resource_name(singular_table_name) %> %>
10
+ </p>
11
+ <%% end %>
7
12
  </div>
8
13
 
9
- <%%= link_to "New <%= human_name.downcase %>", new_<%= singular_route_name %>_path %>
14
+ <%%= link_to "New <%= human_name.downcase %>", <%= new_helper(type: :path) %> %>
@@ -5,5 +5,5 @@
5
5
  <br>
6
6
 
7
7
  <div>
8
- <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper %>_path %>
8
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %> %>
9
9
  </div>