railties 7.0.0.alpha2 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
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>