railties 7.0.0.rc3 → 7.0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +46 -0
  3. data/MIT-LICENSE +1 -1
  4. data/lib/rails/application/configuration.rb +13 -4
  5. data/lib/rails/application/finisher.rb +0 -1
  6. data/lib/rails/application.rb +4 -1
  7. data/lib/rails/autoloaders/inflector.rb +1 -1
  8. data/lib/rails/autoloaders.rb +40 -36
  9. data/lib/rails/commands/dbconsole/dbconsole_command.rb +10 -7
  10. data/lib/rails/gem_version.rb +2 -2
  11. data/lib/rails/generators/actions.rb +30 -13
  12. data/lib/rails/generators/app_base.rb +77 -54
  13. data/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt +2 -2
  14. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +7 -2
  15. data/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt +1 -1
  16. data/lib/rails/generators/erb/scaffold/templates/partial.html.erb.tt +0 -3
  17. data/lib/rails/generators/erb/scaffold/templates/show.html.erb.tt +3 -3
  18. data/lib/rails/generators/generated_attribute.rb +2 -2
  19. data/lib/rails/generators/named_base.rb +10 -10
  20. data/lib/rails/generators/rails/app/app_generator.rb +14 -0
  21. data/lib/rails/generators/rails/app/templates/Gemfile.tt +10 -14
  22. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +0 -31
  23. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +1 -1
  24. data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +3 -1
  25. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_0.rb.tt +0 -4
  26. data/lib/rails/generators/rails/plugin/plugin_generator.rb +39 -16
  27. data/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt +1 -1
  28. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +8 -30
  29. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +0 -5
  30. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt +5 -5
  31. data/lib/rails/generators/testing/behaviour.rb +2 -2
  32. data/lib/rails/tasks/framework.rake +5 -1
  33. data/lib/rails/templates/rails/welcome/index.html.erb +62 -49
  34. data/lib/rails.rb +1 -2
  35. metadata +14 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4faffb109d7c8de979dd145a095fb9ab2cecd14b0c04ba22a59bd993bbc876fc
4
- data.tar.gz: a707973415707a90df0bef3b4d7ceee7394e567c1dcd7e502df793147fe82f60
3
+ metadata.gz: 993d11321ed1aeb092a3b166db0ce63224c6f3a479829f2df6b5c380158723a5
4
+ data.tar.gz: 438510fc4ca0edce2d8af8ea5d24b84d4ca9925a5d1eb2218c11ef3b78ca1bb5
5
5
  SHA512:
6
- metadata.gz: c05ecaa835e442827306d60819e5325fb49453764e8c3cdfeb9dd8e83356fd22e7ec7b8225daa7ab1b0e660a6381f9f76f62aec853b68c7591950952ab544342
7
- data.tar.gz: 483f9b60ee65a85d338b34fcdd9847845c9a86b76bf28c6ca967fa9e16ea8e01d505f7093647e4c6d2cda8f22e1d7e5cfc171ceb06feed88e5900ff5dd2326ea
6
+ metadata.gz: cbbd3012ed38a130373257fc028d03aeb4274fe8ca7ad17bf274b1f0ccc33f219c30e208500ab010c4f9ca7b076c46abb41a710cbeff91dc20a4705c44a17f3a
7
+ data.tar.gz: d2621cadc73593b540f825314c56c434de2e461c5b35317a4a5d32516f67e9528fee4017f93c4657b660fe9f08e09f0cd9c64a646bd3cb030a3b9fad1fc708e4
data/CHANGELOG.md CHANGED
@@ -1,3 +1,45 @@
1
+ ## Rails 7.0.2.1 (February 11, 2022) ##
2
+
3
+ * No changes.
4
+
5
+
6
+ ## Rails 7.0.2 (February 08, 2022) ##
7
+
8
+ * No changes.
9
+
10
+
11
+ ## Rails 7.0.1 (January 06, 2022) ##
12
+
13
+ * Prevent duplicate entries in plugin Gemfile.
14
+
15
+ *Jonathan Hefner*
16
+
17
+ * Fix asset pipeline errors for plugin dummy apps.
18
+
19
+ *Jonathan Hefner*
20
+
21
+ * Fix generated route revocation.
22
+
23
+ *Jonathan Hefner*
24
+
25
+ * Addresses an issue in which Sidekiq jobs could not reload certain
26
+ namespaces.
27
+
28
+ See [fxn/zeitwerk#198](https://github.com/fxn/zeitwerk/issues/198) for
29
+ details.
30
+
31
+ *Xavier Noria*
32
+
33
+ * Fix plugin generator to a plugin that pass all the tests.
34
+
35
+ *Rafael Mendonça França*
36
+
37
+
38
+ ## Rails 7.0.0 (December 15, 2021) ##
39
+
40
+ * No changes.
41
+
42
+
1
43
  ## Rails 7.0.0.rc3 (December 14, 2021) ##
2
44
 
3
45
  * Allow localhost with a port by default in development
@@ -6,6 +48,10 @@
6
48
 
7
49
  ## Rails 7.0.0.rc2 (December 14, 2021) ##
8
50
 
51
+ * No changes
52
+
53
+ ## Rails 7.0.0.rc1 (December 06, 2021) ##
54
+
9
55
  * Remove deprecated `config` in `dbconsole`.
10
56
 
11
57
  *Rafael Mendonça França*
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2004-2021 David Heinemeier Hansson
1
+ Copyright (c) 2004-2022 David Heinemeier Hansson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -33,8 +33,12 @@ module Rails
33
33
  @filter_parameters = []
34
34
  @filter_redirect = []
35
35
  @helpers_paths = []
36
- @hosts = Rails.env.development? ? ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_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
@@ -77,13 +81,17 @@ module Rails
77
81
  @server_timing = false
78
82
  end
79
83
 
80
- # Loads default configurations. See {the result of the method for each version}[https://guides.rubyonrails.org/configuring.html#results-of-config-load-defaults].
84
+ # Loads default configuration values for a target version. This includes
85
+ # defaults for versions prior to the target version. See the
86
+ # {configuration guide}[https://guides.rubyonrails.org/configuring.html]
87
+ # for the default values associated with a particular version.
81
88
  def load_defaults(target_version)
82
89
  case target_version.to_s
83
90
  when "5.0"
84
91
  if respond_to?(:action_controller)
85
92
  action_controller.per_form_csrf_tokens = true
86
93
  action_controller.forgery_protection_origin_check = true
94
+ action_controller.urlsafe_csrf_tokens = false
87
95
  end
88
96
 
89
97
  ActiveSupport.to_time_preserves_timezone = true
@@ -169,7 +177,7 @@ module Rails
169
177
  end
170
178
 
171
179
  if respond_to?(:action_controller)
172
- action_controller.urlsafe_csrf_tokens = true
180
+ action_controller.delete(:urlsafe_csrf_tokens)
173
181
  end
174
182
 
175
183
  if respond_to?(:action_view)
@@ -236,6 +244,7 @@ module Rails
236
244
  " -frames:v 1 -f image2"
237
245
 
238
246
  active_storage.variant_processor = :vips
247
+ active_storage.multiple_file_field_include_hidden = true
239
248
  end
240
249
 
241
250
  if respond_to?(:active_record)
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "zeitwerk"
4
3
  require "active_support/core_ext/string/inflections"
5
4
  require "active_support/core_ext/array/conversions"
6
5
  require "active_support/descendants_tracker"
@@ -10,6 +10,7 @@ require "active_support/hash_with_indifferent_access"
10
10
  require "active_support/configuration_file"
11
11
  require "rails/engine"
12
12
  require "rails/secrets"
13
+ require "rails/autoloaders"
13
14
 
14
15
  module Rails
15
16
  # An Engine with the responsibility of coordinating the whole boot process.
@@ -95,7 +96,7 @@ module Rails
95
96
 
96
97
  attr_accessor :assets, :sandbox
97
98
  alias_method :sandbox?, :sandbox
98
- attr_reader :reloaders, :reloader, :executor
99
+ attr_reader :reloaders, :reloader, :executor, :autoloaders
99
100
 
100
101
  delegate :default_url_options, :default_url_options=, to: :routes
101
102
 
@@ -117,6 +118,8 @@ module Rails
117
118
  @reloader = Class.new(ActiveSupport::Reloader)
118
119
  @reloader.executor = @executor
119
120
 
121
+ @autoloaders = Rails::Autoloaders.new
122
+
120
123
  # are these actually used?
121
124
  @initial_variable_values = initial_variable_values
122
125
  @block = block
@@ -3,7 +3,7 @@
3
3
  require "active_support/inflector"
4
4
 
5
5
  module Rails
6
- module Autoloaders
6
+ class Autoloaders
7
7
  module Inflector # :nodoc:
8
8
  # Concurrent::Map is not needed. This is a private class, and overrides
9
9
  # must be defined while the application boots.
@@ -1,44 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "zeitwerk"
4
-
5
3
  module Rails
6
- module Autoloaders # :nodoc:
4
+ class Autoloaders # :nodoc:
7
5
  require_relative "autoloaders/inflector"
8
6
 
9
- class << self
10
- include Enumerable
11
-
12
- def main
13
- @main ||= Zeitwerk::Loader.new.tap do |loader|
14
- loader.tag = "rails.main"
15
- loader.inflector = Inflector
16
- end
17
- end
18
-
19
- def once
20
- @once ||= Zeitwerk::Loader.new.tap do |loader|
21
- loader.tag = "rails.once"
22
- loader.inflector = Inflector
23
- end
24
- end
25
-
26
- def each
27
- yield main
28
- yield once
29
- end
30
-
31
- def logger=(logger)
32
- each { |loader| loader.logger = logger }
33
- end
34
-
35
- def log!
36
- each(&:log!)
37
- end
38
-
39
- def zeitwerk_enabled?
40
- true
41
- end
7
+ include Enumerable
8
+
9
+ attr_reader :main, :once
10
+
11
+ def initialize
12
+ # This `require` delays loading the library on purpose.
13
+ #
14
+ # In Rails 7.0.0, railties/lib/rails.rb loaded Zeitwerk as a side-effect,
15
+ # but a couple of edge cases related to Bundler and Bootsnap showed up.
16
+ # They had to do with order of decoration of `Kernel#require`, something
17
+ # the three of them do.
18
+ #
19
+ # Delaying this `require` up to this point is a convenient trade-off.
20
+ require "zeitwerk"
21
+
22
+ @main = Zeitwerk::Loader.new
23
+ @main.tag = "rails.main"
24
+ @main.inflector = Inflector
25
+
26
+ @once = Zeitwerk::Loader.new
27
+ @once.tag = "rails.once"
28
+ @once.inflector = Inflector
29
+ end
30
+
31
+ def each
32
+ yield main
33
+ yield once
34
+ end
35
+
36
+ def logger=(logger)
37
+ each { |loader| loader.logger = logger }
38
+ end
39
+
40
+ def log!
41
+ each(&:log!)
42
+ end
43
+
44
+ def zeitwerk_enabled?
45
+ true
42
46
  end
43
47
  end
44
48
  end
@@ -97,15 +97,18 @@ module Rails
97
97
  def db_config
98
98
  return @db_config if defined?(@db_config)
99
99
 
100
- # We need to check whether the user passed the database the
101
- # first time around to show a consistent error message to people
102
- # relying on 2-level database configuration.
103
-
104
- @db_config = configurations.configs_for(env_name: environment, name: database, include_hidden: true)
100
+ # If the user provided a database, use that. Otherwise find
101
+ # the first config in the database.yml
102
+ if database
103
+ @db_config = configurations.configs_for(env_name: environment, name: database, include_hidden: true)
104
+ else
105
+ @db_config = configurations.find_db_config(environment)
106
+ end
105
107
 
106
108
  unless @db_config
109
+ missing_db = database ? "'#{database}' database is not" : "No databases are"
107
110
  raise ActiveRecord::AdapterNotSpecified,
108
- "'#{database}' database is not configured for '#{environment}'. Available configuration: #{configurations.inspect}"
111
+ "#{missing_db} configured for '#{environment}'. Available configuration: #{configurations.inspect}"
109
112
  end
110
113
 
111
114
  @db_config
@@ -116,7 +119,7 @@ module Rails
116
119
  end
117
120
 
118
121
  def database
119
- @options.fetch(:database, "primary")
122
+ @options[:database]
120
123
  end
121
124
 
122
125
  private
@@ -9,8 +9,8 @@ module Rails
9
9
  module VERSION
10
10
  MAJOR = 7
11
11
  MINOR = 0
12
- TINY = 0
13
- PRE = "rc3"
12
+ TINY = 2
13
+ PRE = "1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -279,26 +279,32 @@ module Rails
279
279
  # route "root 'welcome#index'"
280
280
  # route "root 'admin#index'", namespace: :admin
281
281
  def route(routing_code, namespace: nil)
282
- routing_code = Array(namespace).reverse.reduce(routing_code) do |code, ns|
283
- "namespace :#{ns} do\n#{optimize_indentation(code, 2)}end"
282
+ namespace = Array(namespace)
283
+ namespace_pattern = route_namespace_pattern(namespace)
284
+ routing_code = namespace.reverse.reduce(routing_code) do |code, name|
285
+ "namespace :#{name} do\n#{rebase_indentation(code, 2)}end"
284
286
  end
285
287
 
286
288
  log :route, routing_code
287
289
 
288
- after_pattern = Array(namespace).each_with_index.reverse_each.reduce(nil) do |pattern, (ns, i)|
289
- margin = "\\#{i + 1}[ ]{2}"
290
- "(?:(?:^[ ]*\n|^#{margin}.*\n)*?^(#{margin})namespace :#{ns} do\n#{pattern})?"
291
- end.then do |pattern|
292
- /^([ ]*).+\.routes\.draw do[ ]*\n#{pattern}/
293
- end
294
-
295
290
  in_root do
296
- if existing = match_file("config/routes.rb", after_pattern)
297
- base_indent, *, prev_indent = existing.captures.compact.map(&:length)
298
- routing_code = optimize_indentation(routing_code, base_indent + 2).lines.grep_v(/^[ ]{,#{prev_indent}}\S/).join
291
+ if namespace_match = match_file("config/routes.rb", namespace_pattern)
292
+ base_indent, *, existing_block_indent = namespace_match.captures.compact.map(&:length)
293
+ existing_line_pattern = /^[ ]{,#{existing_block_indent}}\S.+\n?/
294
+ routing_code = rebase_indentation(routing_code, base_indent + 2).gsub(existing_line_pattern, "")
295
+ namespace_pattern = /#{Regexp.escape namespace_match.to_s}/
299
296
  end
300
297
 
301
- inject_into_file "config/routes.rb", routing_code, after: after_pattern, verbose: false, force: false
298
+ inject_into_file "config/routes.rb", routing_code, after: namespace_pattern, verbose: false, force: false
299
+
300
+ if behavior == :revoke && namespace.any? && namespace_match
301
+ empty_block_pattern = /(#{namespace_pattern})((?:\s*end\n){1,#{namespace.size}})/
302
+ gsub_file "config/routes.rb", empty_block_pattern, verbose: false, force: true do |matched|
303
+ beginning, ending = empty_block_pattern.match(matched).captures
304
+ ending.sub!(/\A\s*end\n/, "") while !ending.empty? && beginning.sub!(/^[ ]*namespace .+ do\n\s*\z/, "")
305
+ beginning + ending
306
+ end
307
+ end
302
308
  end
303
309
  end
304
310
 
@@ -363,6 +369,7 @@ module Rails
363
369
  return "#{value}\n" unless value.is_a?(String)
364
370
  "#{value.strip_heredoc.indent(amount).chomp}\n"
365
371
  end
372
+ alias rebase_indentation optimize_indentation
366
373
 
367
374
  # Indent the +Gemfile+ to the depth of @indentation
368
375
  def indentation # :doc:
@@ -387,6 +394,16 @@ module Rails
387
394
  def match_file(path, pattern)
388
395
  File.read(path).match(pattern) if File.exist?(path)
389
396
  end
397
+
398
+ def route_namespace_pattern(namespace)
399
+ namespace.each_with_index.reverse_each.reduce(nil) do |pattern, (name, i)|
400
+ cummulative_margin = "\\#{i + 1}[ ]{2}"
401
+ blank_or_indented_line = "^[ ]*\n|^#{cummulative_margin}.*\n"
402
+ "(?:(?:#{blank_or_indented_line})*?^(#{cummulative_margin})namespace :#{name} do\n#{pattern})?"
403
+ end.then do |pattern|
404
+ /^([ ]*).+\.routes\.draw do[ ]*\n#{pattern}/
405
+ end
406
+ end
390
407
  end
391
408
  end
392
409
  end
@@ -100,23 +100,26 @@ module Rails
100
100
  desc: "Show this help message and quit"
101
101
  end
102
102
 
103
- def initialize(*)
103
+ def initialize(positional_argv, option_argv, *)
104
+ @argv = [*positional_argv, *option_argv]
104
105
  @gem_filter = lambda { |gem| true }
105
106
  super
106
107
  end
107
108
 
108
109
  private
109
110
  def gemfile_entries # :doc:
110
- [rails_gemfile_entry,
111
- asset_pipeline_gemfile_entry,
112
- database_gemfile_entry,
113
- web_server_gemfile_entry,
114
- javascript_gemfile_entry,
115
- hotwire_gemfile_entry,
116
- css_gemfile_entry,
117
- jbuilder_gemfile_entry,
118
- psych_gemfile_entry,
119
- cable_gemfile_entry].flatten.find_all(&@gem_filter)
111
+ [
112
+ rails_gemfile_entry,
113
+ asset_pipeline_gemfile_entry,
114
+ database_gemfile_entry,
115
+ web_server_gemfile_entry,
116
+ javascript_gemfile_entry,
117
+ hotwire_gemfile_entry,
118
+ css_gemfile_entry,
119
+ jbuilder_gemfile_entry,
120
+ psych_gemfile_entry,
121
+ cable_gemfile_entry,
122
+ ].flatten.compact.select(&@gem_filter)
120
123
  end
121
124
 
122
125
  def builder # :doc:
@@ -158,7 +161,8 @@ module Rails
158
161
  end
159
162
 
160
163
  def database_gemfile_entry # :doc:
161
- return [] if options[:skip_active_record]
164
+ return if options[:skip_active_record]
165
+
162
166
  gem_name, gem_version = gem_for_database
163
167
  GemfileEntry.version gem_name, gem_version,
164
168
  "Use #{options[:database]} as the database for Active Record"
@@ -169,15 +173,13 @@ module Rails
169
173
  end
170
174
 
171
175
  def asset_pipeline_gemfile_entry
172
- return [] if options[:skip_asset_pipeline]
176
+ return if options[:skip_asset_pipeline]
173
177
 
174
178
  if options[:asset_pipeline] == "sprockets"
175
- GemfileEntry.version "sprockets-rails", ">= 3.4.1",
179
+ GemfileEntry.floats "sprockets-rails",
176
180
  "The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]"
177
181
  elsif options[:asset_pipeline] == "propshaft"
178
- GemfileEntry.version "propshaft", ">= 0.4.1", "The modern asset pipeline for Rails [https://github.com/rails/propshaft/]"
179
- else
180
- []
182
+ GemfileEntry.floats "propshaft", "The modern asset pipeline for Rails [https://github.com/rails/propshaft]"
181
183
  end
182
184
  end
183
185
 
@@ -255,39 +257,40 @@ module Rails
255
257
  new(name, version, comment)
256
258
  end
257
259
 
260
+ def self.floats(name, comment = nil)
261
+ new(name, nil, comment)
262
+ end
263
+
258
264
  def self.path(name, path, comment = nil)
259
265
  new(name, nil, comment, path: path)
260
266
  end
261
267
 
262
- def version
263
- version = super
264
-
265
- if version.is_a?(Array)
266
- version.join('", "')
267
- else
268
- version
269
- end
268
+ def to_s
269
+ [
270
+ (comment.gsub(/^/, "# ").chomp + "\n" if comment),
271
+ ("# " if commented_out),
272
+ "gem \"#{name}\"",
273
+ *Array(version).map { |constraint| ", \"#{constraint}\"" },
274
+ *options.map { |key, value| ", #{key}: #{value.inspect}" },
275
+ ].compact.join
270
276
  end
271
277
  end
272
278
 
279
+ def rails_prerelease?
280
+ options.dev? || options.edge? || options.main?
281
+ end
282
+
273
283
  def rails_gemfile_entry
274
284
  if options.dev?
275
- [
276
- GemfileEntry.path("rails", Rails::Generators::RAILS_DEV_PATH, "Use local checkout of Rails")
277
- ]
285
+ GemfileEntry.path("rails", Rails::Generators::RAILS_DEV_PATH, "Use local checkout of Rails")
278
286
  elsif options.edge?
279
287
  edge_branch = Rails.gem_version.prerelease? ? "main" : [*Rails.gem_version.segments.first(2), "stable"].join("-")
280
- [
281
- GemfileEntry.github("rails", "rails/rails", edge_branch, "Use specific branch of Rails")
282
- ]
288
+ GemfileEntry.github("rails", "rails/rails", edge_branch, "Use specific branch of Rails")
283
289
  elsif options.main?
284
- [
285
- GemfileEntry.github("rails", "rails/rails", "main", "Use main development branch of Rails")
286
- ]
290
+ GemfileEntry.github("rails", "rails/rails", "main", "Use main development branch of Rails")
287
291
  else
288
- [GemfileEntry.version("rails",
289
- rails_version_specifier,
290
- %(Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"))]
292
+ GemfileEntry.version("rails", rails_version_specifier,
293
+ %(Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"))
291
294
  end
292
295
  end
293
296
 
@@ -305,29 +308,28 @@ module Rails
305
308
  end
306
309
 
307
310
  def jbuilder_gemfile_entry
308
- return [] if options[:skip_jbuilder]
309
- comment = "Build JSON APIs with ease [https://github.com/rails/jbuilder]"
310
- GemfileEntry.new "jbuilder", "~> 2.11", comment, {}, options[:api]
311
+ return if options[:skip_jbuilder]
312
+ GemfileEntry.new "jbuilder", nil, "Build JSON APIs with ease [https://github.com/rails/jbuilder]", {}, options[:api]
311
313
  end
312
314
 
313
315
  def javascript_gemfile_entry
314
- return [] if options[:skip_javascript]
316
+ return if options[:skip_javascript]
315
317
 
316
318
  if adjusted_javascript_option == "importmap"
317
- GemfileEntry.version("importmap-rails", ">= 0.9.2", "Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]")
319
+ GemfileEntry.floats "importmap-rails", "Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]"
318
320
  else
319
- GemfileEntry.version "jsbundling-rails", ">= 0.2.2", "Bundle and transpile JavaScript [https://github.com/rails/jsbundling-rails]"
321
+ GemfileEntry.floats "jsbundling-rails", "Bundle and transpile JavaScript [https://github.com/rails/jsbundling-rails]"
320
322
  end
321
323
  end
322
324
 
323
325
  def hotwire_gemfile_entry
324
- return [] if options[:skip_javascript] || options[:skip_hotwire]
326
+ return if options[:skip_javascript] || options[:skip_hotwire]
325
327
 
326
328
  turbo_rails_entry =
327
- GemfileEntry.version("turbo-rails", ">= 0.9.0", "Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]")
329
+ GemfileEntry.floats "turbo-rails", "Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]"
328
330
 
329
331
  stimulus_rails_entry =
330
- GemfileEntry.version("stimulus-rails", ">= 0.7.3", "Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]")
332
+ GemfileEntry.floats "stimulus-rails", "Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]"
331
333
 
332
334
  [ turbo_rails_entry, stimulus_rails_entry ]
333
335
  end
@@ -347,17 +349,17 @@ module Rails
347
349
  end
348
350
 
349
351
  def css_gemfile_entry
350
- return [] unless options[:css]
352
+ return unless options[:css]
351
353
 
352
354
  if !using_node? && options[:css] == "tailwind"
353
- GemfileEntry.version("tailwindcss-rails", ">= 0.5.3", "Use Tailwind CSS [https://github.com/rails/tailwindcss-rails]")
355
+ GemfileEntry.floats "tailwindcss-rails", "Use Tailwind CSS [https://github.com/rails/tailwindcss-rails]"
354
356
  else
355
- GemfileEntry.version("cssbundling-rails", ">= 0.2.7", "Bundle and process CSS [https://github.com/rails/cssbundling-rails]")
357
+ GemfileEntry.floats "cssbundling-rails", "Bundle and process CSS [https://github.com/rails/cssbundling-rails]"
356
358
  end
357
359
  end
358
360
 
359
361
  def psych_gemfile_entry
360
- return [] unless defined?(Rubinius)
362
+ return unless defined?(Rubinius)
361
363
 
362
364
  comment = "Use Psych as the YAML engine, instead of Syck, so serialized " \
363
365
  "data can be read safely from different rubies (see http://git.io/uuLVag)"
@@ -365,11 +367,10 @@ module Rails
365
367
  end
366
368
 
367
369
  def cable_gemfile_entry
368
- return [] if options[:skip_action_cable]
370
+ return if options[:skip_action_cable]
371
+
369
372
  comment = "Use Redis adapter to run Action Cable in production"
370
- gems = []
371
- gems << GemfileEntry.new("redis", "~> 4.0", comment, {}, true)
372
- gems
373
+ GemfileEntry.new("redis", "~> 4.0", comment, {}, true)
373
374
  end
374
375
 
375
376
  def bundle_command(command, env = {})
@@ -410,6 +411,28 @@ module Rails
410
411
  !options[:skip_bootsnap] && !options[:dev] && !defined?(JRUBY_VERSION)
411
412
  end
412
413
 
414
+ def target_rails_prerelease(self_command = "new")
415
+ return unless rails_prerelease? && bundle_install?
416
+
417
+ if !File.exist?(File.expand_path("Gemfile", destination_root))
418
+ create_file("Gemfile", <<~GEMFILE)
419
+ source "https://rubygems.org"
420
+ git_source(:github) { |repo| "https://github.com/\#{repo}.git" }
421
+ #{rails_gemfile_entry}
422
+ GEMFILE
423
+
424
+ run_bundle
425
+
426
+ @argv[0] = destination_root
427
+ require "shellwords"
428
+ bundle_command("exec rails #{self_command} #{Shellwords.join(@argv)}")
429
+ exit
430
+ else
431
+ remove_file("Gemfile")
432
+ remove_file("Gemfile.lock")
433
+ end
434
+ end
435
+
413
436
  def run_bundle
414
437
  bundle_command("install", "BUNDLE_IGNORE_MESSAGES" => "1") if bundle_install?
415
438
  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>
@@ -3,7 +3,12 @@
3
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>
@@ -14,7 +14,4 @@
14
14
  </p>
15
15
 
16
16
  <% end -%>
17
- <p>
18
- <%%= link_to "Show this <%= human_name.downcase %>", <%= singular_name %> %>
19
- </p>
20
17
  </div>
@@ -3,8 +3,8 @@
3
3
  <%%= render @<%= singular_table_name %> %>
4
4
 
5
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 %>
6
+ <%%= link_to "Edit this <%= human_name.downcase %>", <%= edit_helper(type: :path) %> %> |
7
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %> %>
8
8
 
9
- <%%= button_to "Destroy this <%= human_name.downcase %>", <%= singular_table_name %>_path(@<%= singular_table_name %>), method: :delete %>
9
+ <%%= button_to "Destroy this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %>, method: :delete %>
10
10
  </div>