railties 8.0.0 → 8.1.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +126 -137
- data/README.rdoc +1 -1
- data/lib/minitest/rails_plugin.rb +56 -13
- data/lib/rails/application/bootstrap.rb +6 -3
- data/lib/rails/application/configuration.rb +36 -16
- data/lib/rails/application/default_middleware_stack.rb +1 -1
- data/lib/rails/application/finisher.rb +2 -1
- data/lib/rails/application/routes_reloader.rb +1 -2
- data/lib/rails/application.rb +18 -13
- data/lib/rails/application_controller.rb +2 -0
- data/lib/rails/code_statistics.rb +6 -3
- data/lib/rails/command/base.rb +0 -2
- data/lib/rails/command/environment_argument.rb +0 -1
- data/lib/rails/command.rb +1 -1
- data/lib/rails/commands/app/update_command.rb +5 -0
- data/lib/rails/commands/console/irb_console.rb +7 -16
- data/lib/rails/commands/credentials/credentials_command.rb +25 -5
- data/lib/rails/commands/devcontainer/devcontainer_command.rb +1 -0
- data/lib/rails/commands/encrypted/encrypted_command.rb +0 -1
- data/lib/rails/commands/test/test_command.rb +0 -2
- data/lib/rails/engine/lazy_route_set.rb +8 -11
- data/lib/rails/engine.rb +0 -1
- data/lib/rails/gem_version.rb +2 -2
- data/lib/rails/generators/actions.rb +9 -6
- data/lib/rails/generators/app_base.rb +72 -45
- data/lib/rails/generators/bundle_helper.rb +34 -0
- data/lib/rails/generators/database.rb +1 -1
- data/lib/rails/generators/erb/authentication/authentication_generator.rb +2 -0
- data/lib/rails/generators/erb/scaffold/templates/partial.html.erb.tt +2 -2
- data/lib/rails/generators/generated_attribute.rb +1 -1
- data/lib/rails/generators/migration.rb +0 -1
- data/lib/rails/generators/rails/app/app_generator.rb +31 -11
- data/lib/rails/generators/rails/app/templates/Dockerfile.tt +28 -16
- data/lib/rails/generators/rails/app/templates/Gemfile.tt +8 -3
- data/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt +5 -0
- data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +1 -0
- data/lib/rails/generators/rails/app/templates/bin/bundler-audit.tt +5 -0
- data/lib/rails/generators/rails/app/templates/bin/ci.tt +5 -0
- data/lib/rails/generators/rails/app/templates/bin/rubocop.tt +1 -1
- data/lib/rails/generators/rails/app/templates/bin/setup.tt +1 -0
- data/lib/rails/generators/rails/app/templates/config/bundler-audit.yml.tt +5 -0
- data/lib/rails/generators/rails/app/templates/config/ci.rb.tt +40 -0
- data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +10 -2
- data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +10 -2
- data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +11 -2
- data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +16 -6
- data/lib/rails/generators/rails/app/templates/config/deploy.yml.tt +25 -18
- data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +8 -0
- data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +10 -2
- data/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +4 -0
- data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_1.rb.tt +74 -0
- data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +3 -2
- data/lib/rails/generators/rails/app/templates/config/storage.yml.tt +0 -7
- data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +0 -6
- data/lib/rails/generators/rails/app/templates/dockerignore.tt +6 -0
- data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +111 -23
- data/lib/rails/generators/rails/app/templates/github/dependabot.yml +2 -2
- data/lib/rails/generators/rails/app/templates/kamal-secrets.tt +4 -1
- data/lib/rails/generators/rails/app/templates/public/400.html +26 -5
- data/lib/rails/generators/rails/app/templates/public/404.html +27 -6
- data/lib/rails/generators/rails/app/templates/public/406-unsupported-browser.html +25 -4
- data/lib/rails/generators/rails/app/templates/public/422.html +26 -5
- data/lib/rails/generators/rails/app/templates/public/500.html +27 -6
- data/lib/rails/generators/rails/app/templates/ruby-version.tt +1 -1
- data/lib/rails/generators/rails/authentication/authentication_generator.rb +14 -10
- data/lib/rails/generators/rails/authentication/templates/app/controllers/concerns/authentication.rb.tt +1 -4
- data/lib/rails/generators/rails/authentication/templates/app/controllers/passwords_controller.rb.tt +6 -0
- data/lib/rails/generators/rails/authentication/templates/app/controllers/sessions_controller.rb.tt +2 -2
- data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.html.erb.tt +3 -1
- data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.text.erb.tt +3 -1
- data/lib/rails/generators/rails/benchmark/USAGE +1 -1
- data/lib/rails/generators/rails/benchmark/templates/benchmark.rb.tt +0 -2
- data/lib/rails/generators/rails/db/system/change/change_generator.rb +1 -1
- data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +8 -1
- data/lib/rails/generators/rails/devcontainer/templates/devcontainer/Dockerfile.tt +4 -0
- data/lib/rails/generators/rails/devcontainer/templates/devcontainer/compose.yaml.tt +2 -2
- data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +1 -1
- data/lib/rails/generators/rails/encryption_key_file/encryption_key_file_generator.rb +17 -5
- data/lib/rails/generators/rails/master_key/master_key_generator.rb +0 -12
- data/lib/rails/generators/rails/plugin/plugin_generator.rb +1 -0
- data/lib/rails/generators/rails/plugin/templates/Rakefile.tt +0 -4
- data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +23 -11
- data/lib/rails/generators/rails/plugin/templates/github/dependabot.yml +2 -2
- data/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt +2 -2
- data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt +2 -2
- data/lib/rails/generators/rails/script/USAGE +1 -1
- data/lib/rails/generators/test_unit/authentication/authentication_generator.rb +17 -0
- data/lib/rails/generators/test_unit/authentication/templates/test/controllers/passwords_controller_test.rb.tt +67 -0
- data/lib/rails/generators/test_unit/authentication/templates/test/controllers/sessions_controller_test.rb +33 -0
- data/lib/rails/generators/test_unit/authentication/templates/test/models/user_test.rb.tt +4 -3
- data/lib/rails/generators/test_unit/authentication/templates/test/test_helpers/session_test_helper.rb.tt +19 -0
- data/lib/rails/generators/test_unit/model/templates/fixtures.yml.tt +1 -1
- data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +8 -2
- data/lib/rails/generators/test_unit/scaffold/templates/application_system_test_case.rb.tt +5 -0
- data/lib/rails/generators/testing/behavior.rb +0 -3
- data/lib/rails/generators.rb +8 -6
- data/lib/rails/health_controller.rb +10 -2
- data/lib/rails/info.rb +4 -4
- data/lib/rails/info_controller.rb +4 -5
- data/lib/rails/initializable.rb +63 -19
- data/lib/rails/rack/silence_request.rb +5 -2
- data/lib/rails/railtie/configurable.rb +0 -1
- data/lib/rails/railtie.rb +0 -1
- data/lib/rails/source_annotation_extractor.rb +6 -2
- data/lib/rails/tasks/statistics.rake +3 -21
- data/lib/rails/tasks.rb +1 -3
- data/lib/rails/templates/rails/info/notes.html.erb +23 -0
- data/lib/rails/templates/rails/mailers/email.html.erb +3 -2
- data/lib/rails/templates/rails/welcome/index.html.erb +19 -3
- data/lib/rails/test_unit/line_filtering.rb +24 -3
- data/lib/rails/test_unit/reporter.rb +12 -6
- data/lib/rails/test_unit/runner.rb +15 -8
- data/lib/rails/test_unit/test_parser.rb +18 -15
- data/lib/rails.rb +9 -2
- metadata +37 -21
- data/lib/rails/console/methods.rb +0 -7
- data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_0.rb.tt +0 -30
- data/lib/rails/generators/test_unit/plugin/plugin_generator.rb +0 -15
- data/lib/rails/generators/test_unit/plugin/templates/%file_name%_test.rb.tt +0 -7
- data/lib/rails/generators/test_unit/plugin/templates/test_helper.rb +0 -2
- /data/lib/rails/generators/{rails → test_unit}/authentication/templates/test/mailers/previews/passwords_mailer_preview.rb.tt +0 -0
data/lib/rails/application.rb
CHANGED
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require "yaml"
|
|
4
4
|
require "active_support/core_ext/hash/keys"
|
|
5
|
-
require "active_support/core_ext/object/blank"
|
|
6
5
|
require "active_support/key_generator"
|
|
7
6
|
require "active_support/message_verifiers"
|
|
8
|
-
require "active_support/deprecation"
|
|
9
7
|
require "active_support/encrypted_configuration"
|
|
10
8
|
require "active_support/hash_with_indifferent_access"
|
|
11
9
|
require "active_support/configuration_file"
|
|
@@ -158,7 +156,11 @@ module Rails
|
|
|
158
156
|
|
|
159
157
|
# Reload application routes regardless if they changed or not.
|
|
160
158
|
def reload_routes!
|
|
161
|
-
routes_reloader.
|
|
159
|
+
if routes_reloader.execute_unless_loaded
|
|
160
|
+
routes_reloader.loaded = false
|
|
161
|
+
else
|
|
162
|
+
routes_reloader.reload!
|
|
163
|
+
end
|
|
162
164
|
end
|
|
163
165
|
|
|
164
166
|
def reload_routes_unless_loaded # :nodoc:
|
|
@@ -459,18 +461,21 @@ module Rails
|
|
|
459
461
|
# is used to create all ActiveSupport::MessageVerifier and ActiveSupport::MessageEncryptor instances,
|
|
460
462
|
# including the ones that sign and encrypt cookies.
|
|
461
463
|
#
|
|
462
|
-
#
|
|
463
|
-
#
|
|
464
|
+
# We look for it first in <tt>ENV["SECRET_KEY_BASE"]</tt>, then in
|
|
465
|
+
# +credentials.secret_key_base+. For most applications, the correct place
|
|
466
|
+
# to store it is in the encrypted credentials file.
|
|
464
467
|
#
|
|
465
|
-
#
|
|
466
|
-
#
|
|
467
|
-
#
|
|
468
|
+
# In development and test, if the secret_key_base is still empty, it is
|
|
469
|
+
# randomly generated and stored in a temporary file in
|
|
470
|
+
# <tt>tmp/local_secret.txt</tt>.
|
|
468
471
|
#
|
|
469
|
-
#
|
|
472
|
+
# Generating a random secret_key_base and storing it in
|
|
473
|
+
# <tt>tmp/local_secret.txt</tt> can also be triggered by setting
|
|
474
|
+
# <tt>ENV["SECRET_KEY_BASE_DUMMY"]</tt>. This is useful when precompiling
|
|
475
|
+
# assets for production as part of a build step that otherwise does not
|
|
476
|
+
# need access to the production secrets.
|
|
470
477
|
#
|
|
471
|
-
#
|
|
472
|
-
# then +credentials.secret_key_base+. For most applications, the correct place to store it is in the
|
|
473
|
-
# encrypted credentials file.
|
|
478
|
+
# Dockerfile example: <tt>RUN SECRET_KEY_BASE_DUMMY=1 bundle exec rails assets:precompile</tt>.
|
|
474
479
|
def secret_key_base
|
|
475
480
|
config.secret_key_base
|
|
476
481
|
end
|
|
@@ -609,7 +614,7 @@ module Rails
|
|
|
609
614
|
end
|
|
610
615
|
|
|
611
616
|
def railties_initializers(current) # :nodoc:
|
|
612
|
-
initializers =
|
|
617
|
+
initializers = Initializable::Collection.new
|
|
613
618
|
ordered_railties.reverse.flatten.each do |r|
|
|
614
619
|
if r == self
|
|
615
620
|
initializers += current
|
|
@@ -42,14 +42,17 @@ module Rails
|
|
|
42
42
|
|
|
43
43
|
HEADERS = { lines: " Lines", code_lines: " LOC", classes: "Classes", methods: "Methods" }
|
|
44
44
|
|
|
45
|
+
PATTERN = /^(?!\.).*?\.(rb|js|ts|css|scss|coffee|rake|erb)$/
|
|
46
|
+
|
|
45
47
|
class_attribute :directories, default: DIRECTORIES
|
|
46
48
|
class_attribute :test_types, default: TEST_TYPES
|
|
49
|
+
class_attribute :pattern, default: PATTERN
|
|
47
50
|
|
|
48
|
-
# Add directories to the output of the
|
|
51
|
+
# Add directories to the output of the <tt>bin/rails stats</tt> command.
|
|
49
52
|
#
|
|
50
53
|
# Rails::CodeStatistics.register_directory("My Directory", "path/to/dir")
|
|
51
54
|
#
|
|
52
|
-
# For directories that contain test code, set the
|
|
55
|
+
# For directories that contain test code, set the <tt>test_directory</tt> argument to true.
|
|
53
56
|
#
|
|
54
57
|
# Rails::CodeStatistics.register_directory("Model specs", "spec/models", test_directory: true)
|
|
55
58
|
def self.register_directory(label, path, test_directory: false)
|
|
@@ -81,7 +84,7 @@ module Rails
|
|
|
81
84
|
Hash[@pairs.map { |pair| [pair.first, calculate_directory_statistics(pair.last)] }]
|
|
82
85
|
end
|
|
83
86
|
|
|
84
|
-
def calculate_directory_statistics(directory, pattern =
|
|
87
|
+
def calculate_directory_statistics(directory, pattern = self.class.pattern)
|
|
85
88
|
stats = Rails::CodeStatisticsCalculator.new
|
|
86
89
|
|
|
87
90
|
Dir.foreach(directory) do |file_name|
|
data/lib/rails/command/base.rb
CHANGED
data/lib/rails/command.rb
CHANGED
|
@@ -12,6 +12,9 @@ module Rails
|
|
|
12
12
|
|
|
13
13
|
desc "update", "Update configs and some other initially generated files (or use just update:configs or update:bin)"
|
|
14
14
|
def perform
|
|
15
|
+
require_application!
|
|
16
|
+
Rails.application.deprecators.silenced = true
|
|
17
|
+
|
|
15
18
|
configs
|
|
16
19
|
bin
|
|
17
20
|
public_directory
|
|
@@ -70,7 +73,9 @@ module Rails
|
|
|
70
73
|
skip_action_text: !defined?(ActionText::Engine),
|
|
71
74
|
skip_action_cable: !defined?(ActionCable::Engine),
|
|
72
75
|
skip_brakeman: skip_gem?("brakeman"),
|
|
76
|
+
skip_bundler_audit: skip_gem?("bundler-audit"),
|
|
73
77
|
skip_rubocop: skip_gem?("rubocop"),
|
|
78
|
+
skip_thruster: skip_gem?("thruster"),
|
|
74
79
|
skip_test: !defined?(Rails::TestUnitRailtie),
|
|
75
80
|
skip_system_test: Rails.application.config.generators.system_tests.nil?,
|
|
76
81
|
skip_asset_pipeline: asset_pipeline.nil?,
|
|
@@ -31,6 +31,7 @@ module Rails
|
|
|
31
31
|
|
|
32
32
|
def execute(*)
|
|
33
33
|
app = Rails.application
|
|
34
|
+
app.reload_routes_unless_loaded
|
|
34
35
|
session = ActionDispatch::Integration::Session.new(app)
|
|
35
36
|
|
|
36
37
|
# This makes app.url_for and app.foo_path available in the console
|
|
@@ -59,22 +60,11 @@ module Rails
|
|
|
59
60
|
end
|
|
60
61
|
end
|
|
61
62
|
|
|
62
|
-
class ReloadCommand < IRB::Command::Base
|
|
63
|
-
category "Rails console"
|
|
64
|
-
description "Reloads the Rails application."
|
|
65
|
-
|
|
66
|
-
def execute(*)
|
|
67
|
-
puts "Reloading..."
|
|
68
|
-
Rails.application.reloader.reload!
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
|
|
72
63
|
IRB::HelperMethod.register(:helper, ControllerHelper)
|
|
73
64
|
IRB::HelperMethod.register(:controller, ControllerInstance)
|
|
74
65
|
IRB::HelperMethod.register(:new_session, NewSession)
|
|
75
66
|
IRB::HelperMethod.register(:app, AppInstance)
|
|
76
67
|
IRB::HelperMethod.register(:reload!, ReloadHelper)
|
|
77
|
-
IRB::Command.register(:reload!, ReloadCommand)
|
|
78
68
|
|
|
79
69
|
class IRBConsole
|
|
80
70
|
def initialize(app)
|
|
@@ -97,12 +87,13 @@ module Rails
|
|
|
97
87
|
|
|
98
88
|
env = colorized_env
|
|
99
89
|
prompt_prefix = "%N(#{env})"
|
|
100
|
-
|
|
90
|
+
# Respect user's configured irb name.
|
|
91
|
+
IRB.conf[:IRB_NAME] = @app.name if IRB.conf[:IRB_NAME] == "irb"
|
|
101
92
|
|
|
102
93
|
IRB.conf[:PROMPT][:RAILS_PROMPT] = {
|
|
103
|
-
PROMPT_I: "#{prompt_prefix}> ",
|
|
104
|
-
PROMPT_S: "#{prompt_prefix}%l ",
|
|
105
|
-
PROMPT_C: "#{prompt_prefix}* ",
|
|
94
|
+
PROMPT_I: "#{prompt_prefix}:%03n> ",
|
|
95
|
+
PROMPT_S: "#{prompt_prefix}:%03n%l ",
|
|
96
|
+
PROMPT_C: "#{prompt_prefix}:%03n* ",
|
|
106
97
|
RETURN: "=> %s\n"
|
|
107
98
|
}
|
|
108
99
|
|
|
@@ -131,7 +122,7 @@ module Rails
|
|
|
131
122
|
when "production"
|
|
132
123
|
IRB::Color.colorize("prod", [:RED])
|
|
133
124
|
else
|
|
134
|
-
Rails.env
|
|
125
|
+
IRB::Color.colorize(Rails.env, [:MAGENTA])
|
|
135
126
|
end
|
|
136
127
|
end
|
|
137
128
|
end
|
|
@@ -35,7 +35,7 @@ module Rails
|
|
|
35
35
|
def show
|
|
36
36
|
load_environment_config!
|
|
37
37
|
|
|
38
|
-
say credentials.read.presence ||
|
|
38
|
+
say credentials.read.presence || missing_credentials!
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
desc "diff", "Enroll/disenroll in decrypted diffs of credentials using git"
|
|
@@ -57,6 +57,26 @@ module Rails
|
|
|
57
57
|
say credentials.content_path.read
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
+
desc "fetch PATH", "Fetch a value in the decrypted credentials"
|
|
61
|
+
def fetch(path)
|
|
62
|
+
load_environment_config!
|
|
63
|
+
|
|
64
|
+
if (yaml = credentials.read)
|
|
65
|
+
begin
|
|
66
|
+
value = YAML.load(yaml)
|
|
67
|
+
value = path.split(".").inject(value) do |doc, key|
|
|
68
|
+
doc.fetch(key)
|
|
69
|
+
end
|
|
70
|
+
say value.to_s
|
|
71
|
+
rescue KeyError, NoMethodError
|
|
72
|
+
say_error "Invalid or missing credential path: #{path}"
|
|
73
|
+
exit 1
|
|
74
|
+
end
|
|
75
|
+
else
|
|
76
|
+
missing_credentials!
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
60
80
|
private
|
|
61
81
|
def config
|
|
62
82
|
Rails.application.config.credentials
|
|
@@ -81,7 +101,6 @@ module Rails
|
|
|
81
101
|
|
|
82
102
|
encryption_key_file_generator = Rails::Generators::EncryptionKeyFileGenerator.new
|
|
83
103
|
encryption_key_file_generator.add_key_file(key_path)
|
|
84
|
-
encryption_key_file_generator.ignore_key_file(key_path)
|
|
85
104
|
end
|
|
86
105
|
|
|
87
106
|
def ensure_credentials_have_been_added
|
|
@@ -115,12 +134,13 @@ module Rails
|
|
|
115
134
|
say "Your application will not be able to load '#{content_path}' until the error has been fixed.", :red
|
|
116
135
|
end
|
|
117
136
|
|
|
118
|
-
def
|
|
137
|
+
def missing_credentials!
|
|
119
138
|
if !credentials.key?
|
|
120
|
-
"Missing '#{key_path}' to decrypt credentials. See `#{executable(:help)}`."
|
|
139
|
+
say_error "Missing '#{key_path}' to decrypt credentials. See `#{executable(:help)}`."
|
|
121
140
|
else
|
|
122
|
-
"File '#{content_path}' does not exist. Use `#{executable(:edit)}` to change that."
|
|
141
|
+
say_error "File '#{content_path}' does not exist. Use `#{executable(:edit)}` to change that."
|
|
123
142
|
end
|
|
143
|
+
exit 1
|
|
124
144
|
end
|
|
125
145
|
|
|
126
146
|
def relative_path(path)
|
|
@@ -22,6 +22,7 @@ module Rails
|
|
|
22
22
|
def devcontainer_options
|
|
23
23
|
@devcontainer_options ||= {
|
|
24
24
|
app_name: Rails.application.railtie_name.chomp("_application"),
|
|
25
|
+
app_folder: File.basename(Rails.root),
|
|
25
26
|
database: !!defined?(ActiveRecord) && database,
|
|
26
27
|
active_storage: !!defined?(ActiveStorage),
|
|
27
28
|
redis: !!((defined?(ActionCable) && !defined?(SolidCable)) || (defined?(ActiveJob) && !defined?(SolidQueue))),
|
|
@@ -45,7 +45,6 @@ module Rails
|
|
|
45
45
|
def ensure_encryption_key_has_been_added
|
|
46
46
|
return if encrypted_configuration.key?
|
|
47
47
|
encryption_key_file_generator.add_key_file(key_path)
|
|
48
|
-
encryption_key_file_generator.ignore_key_file(key_path)
|
|
49
48
|
end
|
|
50
49
|
|
|
51
50
|
def ensure_encrypted_configuration_has_been_added
|
|
@@ -31,8 +31,6 @@ module Rails
|
|
|
31
31
|
Rails::TestUnit::Runner.parse_options(args)
|
|
32
32
|
run_prepare_task if self.args.none?(EXACT_TEST_ARGUMENT_PATTERN)
|
|
33
33
|
Rails::TestUnit::Runner.run(args)
|
|
34
|
-
rescue Rails::TestUnit::InvalidTestError => error
|
|
35
|
-
raise ArgumentError, error.message
|
|
36
34
|
end
|
|
37
35
|
|
|
38
36
|
# Define Thor tasks to avoid going through Rake and booting twice when using bin/rails test:*
|
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
require "action_dispatch/routing/route_set"
|
|
6
6
|
|
|
7
|
+
# :enddoc:
|
|
8
|
+
|
|
7
9
|
module Rails
|
|
8
10
|
class Engine
|
|
9
|
-
class LazyRouteSet < ActionDispatch::Routing::RouteSet
|
|
11
|
+
class LazyRouteSet < ActionDispatch::Routing::RouteSet
|
|
10
12
|
class NamedRouteCollection < ActionDispatch::Routing::RouteSet::NamedRouteCollection
|
|
11
13
|
def route_defined?(name)
|
|
12
14
|
Rails.application&.reload_routes_unless_loaded
|
|
@@ -34,16 +36,6 @@ module Rails
|
|
|
34
36
|
Rails.application&.reload_routes_unless_loaded
|
|
35
37
|
super
|
|
36
38
|
end
|
|
37
|
-
|
|
38
|
-
def polymorphic_url(record_or_hash_or_array, options = {})
|
|
39
|
-
Rails.application&.reload_routes_unless_loaded
|
|
40
|
-
super
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def polymorphic_path(record_or_hash_or_array, options = {})
|
|
44
|
-
Rails.application&.reload_routes_unless_loaded
|
|
45
|
-
super
|
|
46
|
-
end
|
|
47
39
|
end
|
|
48
40
|
|
|
49
41
|
def initialize(config = DEFAULT_CONFIG)
|
|
@@ -68,6 +60,11 @@ module Rails
|
|
|
68
60
|
super
|
|
69
61
|
end
|
|
70
62
|
|
|
63
|
+
def polymorphic_mappings
|
|
64
|
+
Rails.application&.reload_routes_unless_loaded
|
|
65
|
+
super
|
|
66
|
+
end
|
|
67
|
+
|
|
71
68
|
def draw(&block)
|
|
72
69
|
Rails.application&.reload_routes_unless_loaded
|
|
73
70
|
super
|
data/lib/rails/engine.rb
CHANGED
data/lib/rails/gem_version.rb
CHANGED
|
@@ -445,18 +445,17 @@ module Rails
|
|
|
445
445
|
|
|
446
446
|
private
|
|
447
447
|
# Define log for backwards compatibility. If just one argument is sent,
|
|
448
|
-
# invoke say
|
|
449
|
-
# similarly to say_status, this method respects the quiet? option given.
|
|
448
|
+
# invoke +say+, otherwise invoke +say_status+.
|
|
450
449
|
def log(*args) # :doc:
|
|
451
450
|
if args.size == 1
|
|
452
|
-
say args.first.to_s
|
|
451
|
+
say args.first.to_s
|
|
453
452
|
else
|
|
454
453
|
args << (behavior == :invoke ? :green : :red)
|
|
455
454
|
say_status(*args)
|
|
456
455
|
end
|
|
457
456
|
end
|
|
458
457
|
|
|
459
|
-
# Runs the supplied command using either
|
|
458
|
+
# Runs the supplied command using either +rake+ or +rails+
|
|
460
459
|
# based on the executor parameter provided.
|
|
461
460
|
def execute_command(executor, command, options = {}) # :doc:
|
|
462
461
|
log executor, command
|
|
@@ -490,12 +489,16 @@ module Rails
|
|
|
490
489
|
end
|
|
491
490
|
alias rebase_indentation optimize_indentation
|
|
492
491
|
|
|
493
|
-
#
|
|
492
|
+
# Returns a string corresponding to the current indentation level
|
|
493
|
+
# (i.e. 2 * <code>@indentation</code> spaces). See also
|
|
494
|
+
# #with_indentation, which can be used to manage the indentation level.
|
|
494
495
|
def indentation # :doc:
|
|
495
496
|
" " * @indentation
|
|
496
497
|
end
|
|
497
498
|
|
|
498
|
-
#
|
|
499
|
+
# Increases the current indentation indentation level for the duration
|
|
500
|
+
# of the given block, and decreases it after the block ends. Call
|
|
501
|
+
# #indentation to get an indentation string.
|
|
499
502
|
def with_indentation(&block) # :doc:
|
|
500
503
|
@indentation += 1
|
|
501
504
|
instance_eval(&block)
|
|
@@ -7,12 +7,14 @@ require "open-uri"
|
|
|
7
7
|
require "tsort"
|
|
8
8
|
require "uri"
|
|
9
9
|
require "rails/generators"
|
|
10
|
+
require "rails/generators/bundle_helper"
|
|
10
11
|
require "active_support/core_ext/array/extract_options"
|
|
11
12
|
|
|
12
13
|
module Rails
|
|
13
14
|
module Generators
|
|
14
15
|
class AppBase < Base # :nodoc:
|
|
15
16
|
include AppName
|
|
17
|
+
include BundleHelper
|
|
16
18
|
|
|
17
19
|
NODE_LTS_VERSION = "20.11.1"
|
|
18
20
|
BUN_VERSION = "1.0.1"
|
|
@@ -71,7 +73,8 @@ module Rails
|
|
|
71
73
|
class_option :skip_action_cable, type: :boolean, aliases: "-C", default: nil,
|
|
72
74
|
desc: "Skip Action Cable files"
|
|
73
75
|
|
|
74
|
-
class_option :skip_asset_pipeline, type: :boolean, aliases: "-A", default: nil
|
|
76
|
+
class_option :skip_asset_pipeline, type: :boolean, aliases: "-A", default: nil,
|
|
77
|
+
desc: "Skip the asset pipeline setup"
|
|
75
78
|
|
|
76
79
|
class_option :skip_javascript, type: :boolean, aliases: ["-J", "--skip-js"], default: (true if name == "plugin"),
|
|
77
80
|
desc: "Skip JavaScript files"
|
|
@@ -103,6 +106,9 @@ module Rails
|
|
|
103
106
|
class_option :skip_brakeman, type: :boolean, default: nil,
|
|
104
107
|
desc: "Skip brakeman setup"
|
|
105
108
|
|
|
109
|
+
class_option :skip_bundler_audit, type: :boolean, default: nil,
|
|
110
|
+
desc: "Skip bundler-audit setup"
|
|
111
|
+
|
|
106
112
|
class_option :skip_ci, type: :boolean, default: nil,
|
|
107
113
|
desc: "Skip GitHub CI files"
|
|
108
114
|
|
|
@@ -397,6 +403,10 @@ module Rails
|
|
|
397
403
|
options[:skip_brakeman]
|
|
398
404
|
end
|
|
399
405
|
|
|
406
|
+
def skip_bundler_audit?
|
|
407
|
+
options[:skip_bundler_audit]
|
|
408
|
+
end
|
|
409
|
+
|
|
400
410
|
def skip_ci?
|
|
401
411
|
options[:skip_ci]
|
|
402
412
|
end
|
|
@@ -491,7 +501,7 @@ module Rails
|
|
|
491
501
|
def javascript_gemfile_entry
|
|
492
502
|
return if options[:skip_javascript]
|
|
493
503
|
|
|
494
|
-
if
|
|
504
|
+
if using_importmap?
|
|
495
505
|
GemfileEntry.floats "importmap-rails", "Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]"
|
|
496
506
|
else
|
|
497
507
|
GemfileEntry.floats "jsbundling-rails", "Bundle and transpile JavaScript [https://github.com/rails/jsbundling-rails]"
|
|
@@ -510,9 +520,12 @@ module Rails
|
|
|
510
520
|
[ turbo_rails_entry, stimulus_rails_entry ]
|
|
511
521
|
end
|
|
512
522
|
|
|
523
|
+
def using_importmap?
|
|
524
|
+
!options.skip_javascript? && options[:javascript] == "importmap"
|
|
525
|
+
end
|
|
526
|
+
|
|
513
527
|
def using_js_runtime?
|
|
514
|
-
(options[:
|
|
515
|
-
(options[:css] && !%w[tailwind sass].include?(options[:css]))
|
|
528
|
+
!options.skip_javascript? && (!using_importmap? || (options[:css] && !%w[tailwind sass].include?(options[:css])))
|
|
516
529
|
end
|
|
517
530
|
|
|
518
531
|
def using_node?
|
|
@@ -523,26 +536,35 @@ module Rails
|
|
|
523
536
|
using_js_runtime? && %w[bun].include?(options[:javascript])
|
|
524
537
|
end
|
|
525
538
|
|
|
539
|
+
def capture_command(command, pattern = nil)
|
|
540
|
+
output = `#{command}`
|
|
541
|
+
if pattern
|
|
542
|
+
output[pattern]
|
|
543
|
+
else
|
|
544
|
+
output
|
|
545
|
+
end
|
|
546
|
+
rescue SystemCallError
|
|
547
|
+
nil
|
|
548
|
+
end
|
|
549
|
+
|
|
526
550
|
def node_version
|
|
527
551
|
if using_node?
|
|
528
552
|
ENV.fetch("NODE_VERSION") do
|
|
529
|
-
|
|
530
|
-
rescue
|
|
531
|
-
NODE_LTS_VERSION
|
|
553
|
+
capture_command("node --version", /\d+\.\d+\.\d+/) || NODE_LTS_VERSION
|
|
532
554
|
end
|
|
533
555
|
end
|
|
534
556
|
end
|
|
535
557
|
|
|
536
558
|
def dockerfile_yarn_version
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
559
|
+
capture_command("yarn --version", /\d+\.\d+\.\d+/) || "latest"
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
def yarn_through_corepack?
|
|
563
|
+
using_node? and "#{dockerfile_yarn_version}" >= "2"
|
|
540
564
|
end
|
|
541
565
|
|
|
542
566
|
def dockerfile_bun_version
|
|
543
|
-
|
|
544
|
-
rescue
|
|
545
|
-
BUN_VERSION
|
|
567
|
+
capture_command("bun --version", /\d+\.\d+\.\d+/) || BUN_VERSION
|
|
546
568
|
end
|
|
547
569
|
|
|
548
570
|
def dockerfile_binfile_fixups
|
|
@@ -592,7 +614,7 @@ module Rails
|
|
|
592
614
|
|
|
593
615
|
def dockerfile_build_packages
|
|
594
616
|
# start with the essentials
|
|
595
|
-
packages = %w(build-essential git pkg-config)
|
|
617
|
+
packages = %w(build-essential git pkg-config libyaml-dev)
|
|
596
618
|
|
|
597
619
|
# add database support
|
|
598
620
|
packages << database.build_package unless skip_active_record?
|
|
@@ -609,6 +631,19 @@ module Rails
|
|
|
609
631
|
packages.compact.sort
|
|
610
632
|
end
|
|
611
633
|
|
|
634
|
+
def ci_packages
|
|
635
|
+
dockerfile_build_packages - [
|
|
636
|
+
# GitHub Actions doesn't have build-essential,
|
|
637
|
+
# but it's a meta-packages and all its dependencies are already installed.
|
|
638
|
+
"build-essential",
|
|
639
|
+
"git",
|
|
640
|
+
"pkg-config",
|
|
641
|
+
"libyaml-dev",
|
|
642
|
+
"unzip",
|
|
643
|
+
"python-is-python3",
|
|
644
|
+
]
|
|
645
|
+
end
|
|
646
|
+
|
|
612
647
|
def css_gemfile_entry
|
|
613
648
|
return if options[:api]
|
|
614
649
|
return unless options[:css]
|
|
@@ -629,30 +664,9 @@ module Rails
|
|
|
629
664
|
end
|
|
630
665
|
end
|
|
631
666
|
|
|
632
|
-
def
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
# We are going to shell out rather than invoking Bundler::CLI.new(command)
|
|
636
|
-
# because `rails new` loads the Thor gem and on the other hand bundler uses
|
|
637
|
-
# its own vendored Thor, which could be a different version. Running both
|
|
638
|
-
# things in the same process is a recipe for a night with paracetamol.
|
|
639
|
-
#
|
|
640
|
-
# Thanks to James Tucker for the Gem tricks involved in this call.
|
|
641
|
-
_bundle_command = Gem.bin_path("bundler", "bundle")
|
|
642
|
-
|
|
643
|
-
require "bundler"
|
|
644
|
-
Bundler.with_original_env do
|
|
645
|
-
exec_bundle_command(_bundle_command, command, env)
|
|
646
|
-
end
|
|
647
|
-
end
|
|
648
|
-
|
|
649
|
-
def exec_bundle_command(bundle_command, command, env)
|
|
650
|
-
full_command = %Q["#{Gem.ruby}" "#{bundle_command}" #{command}]
|
|
651
|
-
if options[:quiet]
|
|
652
|
-
system(env, full_command, out: File::NULL)
|
|
653
|
-
else
|
|
654
|
-
system(env, full_command)
|
|
655
|
-
end
|
|
667
|
+
def rails_command(command, command_options = {})
|
|
668
|
+
command_options[:capture] = true if options[:quiet]
|
|
669
|
+
super
|
|
656
670
|
end
|
|
657
671
|
|
|
658
672
|
def bundle_install?
|
|
@@ -664,7 +678,7 @@ module Rails
|
|
|
664
678
|
end
|
|
665
679
|
|
|
666
680
|
def depend_on_bootsnap?
|
|
667
|
-
!options[:skip_bootsnap] && !options[:dev] && !
|
|
681
|
+
!options[:skip_bootsnap] && !options[:dev] && !jruby?
|
|
668
682
|
end
|
|
669
683
|
|
|
670
684
|
def target_rails_prerelease(self_command = "new")
|
|
@@ -740,7 +754,7 @@ module Rails
|
|
|
740
754
|
end
|
|
741
755
|
|
|
742
756
|
def add_bundler_platforms
|
|
743
|
-
if bundle_install?
|
|
757
|
+
if bundle_install? && !jruby?
|
|
744
758
|
# The vast majority of Rails apps will be deployed on `x86_64-linux`.
|
|
745
759
|
bundle_command("lock --add-platform=x86_64-linux")
|
|
746
760
|
|
|
@@ -749,10 +763,21 @@ module Rails
|
|
|
749
763
|
end
|
|
750
764
|
end
|
|
751
765
|
|
|
752
|
-
def
|
|
753
|
-
|
|
754
|
-
|
|
766
|
+
def jruby?
|
|
767
|
+
defined?(JRUBY_VERSION)
|
|
768
|
+
end
|
|
769
|
+
|
|
770
|
+
def version_manager_ruby_version
|
|
771
|
+
return ENV["RBENV_VERSION"] if ENV["RBENV_VERSION"]
|
|
772
|
+
return ENV["rvm_ruby_string"] if ENV["rvm_ruby_string"]
|
|
773
|
+
|
|
774
|
+
version = if RUBY_ENGINE == "ruby"
|
|
775
|
+
Gem.ruby_version.to_s.sub(/\.([a-zA-Z])/, '-\1')
|
|
776
|
+
else
|
|
777
|
+
RUBY_ENGINE_VERSION
|
|
755
778
|
end
|
|
779
|
+
|
|
780
|
+
"#{RUBY_ENGINE}-#{version}"
|
|
756
781
|
end
|
|
757
782
|
|
|
758
783
|
def empty_directory_with_keep_file(destination, config = {})
|
|
@@ -765,11 +790,13 @@ module Rails
|
|
|
765
790
|
end
|
|
766
791
|
|
|
767
792
|
def user_default_branch
|
|
768
|
-
@user_default_branch ||=
|
|
793
|
+
@user_default_branch ||= capture_command("git config init.defaultbranch").strip.presence || "main"
|
|
769
794
|
end
|
|
770
795
|
|
|
771
796
|
def git_init_command
|
|
772
|
-
|
|
797
|
+
if capture_command("git config init.defaultbranch").present?
|
|
798
|
+
return "git init"
|
|
799
|
+
end
|
|
773
800
|
|
|
774
801
|
git_version = `git --version`[/\d+\.\d+\.\d+/]
|
|
775
802
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rails
|
|
4
|
+
module Generators
|
|
5
|
+
module BundleHelper # :nodoc:
|
|
6
|
+
def bundle_command(command, env = {}, params = {})
|
|
7
|
+
say_status :run, "bundle #{command}"
|
|
8
|
+
|
|
9
|
+
# We are going to shell out rather than invoking Bundler::CLI.new(command)
|
|
10
|
+
# because `rails new` loads the Thor gem and on the other hand bundler uses
|
|
11
|
+
# its own vendored Thor, which could be a different version. Running both
|
|
12
|
+
# things in the same process is a recipe for a night with paracetamol.
|
|
13
|
+
#
|
|
14
|
+
# Thanks to James Tucker for the Gem tricks involved in this call.
|
|
15
|
+
_bundle_command = Gem.bin_path("bundler", "bundle")
|
|
16
|
+
|
|
17
|
+
require "bundler"
|
|
18
|
+
Bundler.with_original_env do
|
|
19
|
+
exec_bundle_command(_bundle_command, command, env, params)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
def exec_bundle_command(bundle_command, command, env, params)
|
|
25
|
+
full_command = %Q["#{Gem.ruby}" "#{bundle_command}" #{command}]
|
|
26
|
+
if options[:quiet] || params[:quiet]
|
|
27
|
+
system(env, full_command, out: File::NULL)
|
|
28
|
+
else
|
|
29
|
+
system(env, full_command)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|