aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionview/lib/action_view/base.rb2
-rw-r--r--actionview/lib/action_view/file_template.rb4
-rw-r--r--actionview/lib/action_view/template.rb11
-rw-r--r--actionview/lib/action_view/template/handlers/erb/erubi.rb2
-rw-r--r--actionview/lib/action_view/template/resolver.rb40
-rw-r--r--actionview/lib/action_view/testing/resolvers.rb6
-rw-r--r--actionview/test/template/digestor_test.rb2
-rw-r--r--actionview/test/template/lookup_context_test.rb50
-rw-r--r--activerecord/lib/active_record/insert_all.rb8
-rw-r--r--activerecord/test/cases/insert_all_test.rb6
-rw-r--r--activesupport/CHANGELOG.md4
-rw-r--r--activesupport/lib/active_support/core_ext/string/inflections.rb2
-rw-r--r--activesupport/lib/active_support/dependencies/zeitwerk_integration.rb3
-rw-r--r--activesupport/lib/active_support/evented_file_update_checker.rb4
-rw-r--r--activesupport/lib/active_support/inflector/transliterate.rb14
-rw-r--r--activesupport/test/file_update_checker_shared_tests.rb12
-rw-r--r--guides/source/active_record_querying.md7
-rw-r--r--railties/lib/rails/command/environment_argument.rb9
-rw-r--r--railties/lib/rails/commands/credentials/credentials_command.rb7
-rw-r--r--railties/lib/rails/commands/runner/runner_command.rb10
-rw-r--r--railties/lib/rails/commands/server/server_command.rb6
-rw-r--r--railties/test/application/runner_test.rb4
-rw-r--r--railties/test/application/zeitwerk_integration_test.rb33
-rw-r--r--railties/test/commands/credentials_test.rb14
-rw-r--r--railties/test/commands/server_test.rb10
25 files changed, 132 insertions, 138 deletions
diff --git a/actionview/lib/action_view/base.rb b/actionview/lib/action_view/base.rb
index cf71b4803b..5253ef7b0c 100644
--- a/actionview/lib/action_view/base.rb
+++ b/actionview/lib/action_view/base.rb
@@ -267,7 +267,7 @@ module ActionView #:nodoc:
_prepare_context
end
- def run(method, template, locals, buffer, &block)
+ def _run(method, template, locals, buffer, &block)
_old_output_buffer, _old_virtual_path, _old_template = @output_buffer, @virtual_path, @current_template
@current_template = template
@output_buffer = buffer
diff --git a/actionview/lib/action_view/file_template.rb b/actionview/lib/action_view/file_template.rb
index dea02176eb..d838078f94 100644
--- a/actionview/lib/action_view/file_template.rb
+++ b/actionview/lib/action_view/file_template.rb
@@ -22,11 +22,11 @@ module ActionView
# to ensure that references to the template object can be marshalled as well. This means forgoing
# the marshalling of the compiler mutex and instantiating that again on unmarshalling.
def marshal_dump # :nodoc:
- [ @identifier, @handler, @compiled, @locals, @virtual_path, @updated_at, @format, @variant ]
+ [ @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant ]
end
def marshal_load(array) # :nodoc:
- @identifier, @handler, @compiled, @locals, @virtual_path, @updated_at, @format, @variant = *array
+ @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant = *array
@compile_mutex = Mutex.new
end
end
diff --git a/actionview/lib/action_view/template.rb b/actionview/lib/action_view/template.rb
index 2c27e11b9e..e733c6d376 100644
--- a/actionview/lib/action_view/template.rb
+++ b/actionview/lib/action_view/template.rb
@@ -122,10 +122,10 @@ module ActionView
extend Template::Handlers
- attr_reader :source, :identifier, :handler, :original_encoding, :updated_at
+ attr_reader :source, :identifier, :handler, :original_encoding
attr_reader :variable, :format, :variant, :locals, :virtual_path
- def initialize(source, identifier, handler, format: nil, variant: nil, locals: nil, virtual_path: nil, updated_at: Time.now)
+ def initialize(source, identifier, handler, format: nil, variant: nil, locals: nil, virtual_path: nil)
unless locals
ActiveSupport::Deprecation.warn "ActionView::Template#initialize requires a locals parameter"
locals = []
@@ -144,7 +144,6 @@ module ActionView
$1.to_sym
end
- @updated_at = updated_at
@format = format
@variant = variant
@compile_mutex = Mutex.new
@@ -173,7 +172,7 @@ module ActionView
def render(view, locals, buffer = ActionView::OutputBuffer.new, &block)
instrument_render_template do
compile!(view)
- view.run(method_name, self, locals, buffer, &block)
+ view._run(method_name, self, locals, buffer, &block)
end
rescue => e
handle_render_error(view, e)
@@ -261,11 +260,11 @@ module ActionView
# to ensure that references to the template object can be marshalled as well. This means forgoing
# the marshalling of the compiler mutex and instantiating that again on unmarshalling.
def marshal_dump # :nodoc:
- [ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @updated_at, @format, @variant ]
+ [ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant ]
end
def marshal_load(array) # :nodoc:
- @source, @identifier, @handler, @compiled, @locals, @virtual_path, @updated_at, @format, @variant = *array
+ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant = *array
@compile_mutex = Mutex.new
end
diff --git a/actionview/lib/action_view/template/handlers/erb/erubi.rb b/actionview/lib/action_view/template/handlers/erb/erubi.rb
index 247b6d75d1..307b852440 100644
--- a/actionview/lib/action_view/template/handlers/erb/erubi.rb
+++ b/actionview/lib/action_view/template/handlers/erb/erubi.rb
@@ -27,7 +27,7 @@ module ActionView
include action_view_erb_handler_context._routes.url_helpers
class_eval("define_method(:_template) { |local_assigns, output_buffer| #{src} }", @filename || "(erubi)", 0)
}.empty
- view.run(:_template, nil, {}, ActionView::OutputBuffer.new)
+ view._run(:_template, nil, {}, ActionView::OutputBuffer.new)
end
private
diff --git a/actionview/lib/action_view/template/resolver.rb b/actionview/lib/action_view/template/resolver.rb
index 1dc9c9919a..07c44307ff 100644
--- a/actionview/lib/action_view/template/resolver.rb
+++ b/actionview/lib/action_view/template/resolver.rb
@@ -63,26 +63,11 @@ module ActionView
# Cache the templates returned by the block
def cache(key, name, prefix, partial, locals)
- if Resolver.caching?
- @data[key][name][prefix][partial][locals] ||= canonical_no_templates(yield)
- else
- fresh_templates = yield
- cached_templates = @data[key][name][prefix][partial][locals]
-
- if templates_have_changed?(cached_templates, fresh_templates)
- @data[key][name][prefix][partial][locals] = canonical_no_templates(fresh_templates)
- else
- cached_templates || NO_TEMPLATES
- end
- end
+ @data[key][name][prefix][partial][locals] ||= canonical_no_templates(yield)
end
def cache_query(query) # :nodoc:
- if Resolver.caching?
- @query_cache[query] ||= canonical_no_templates(yield)
- else
- yield
- end
+ @query_cache[query] ||= canonical_no_templates(yield)
end
def clear
@@ -112,19 +97,6 @@ module ActionView
def canonical_no_templates(templates)
templates.empty? ? NO_TEMPLATES : templates
end
-
- def templates_have_changed?(cached_templates, fresh_templates)
- # if either the old or new template list is empty, we don't need to (and can't)
- # compare modification times, and instead just check whether the lists are different
- if cached_templates.blank? || fresh_templates.blank?
- return fresh_templates.blank? != cached_templates.blank?
- end
-
- cached_templates_max_updated_at = cached_templates.map(&:updated_at).max
-
- # if a template has changed, it will be now be newer than all the cached templates
- fresh_templates.any? { |t| t.updated_at > cached_templates_max_updated_at }
- end
end
cattr_accessor :caching, default: true
@@ -218,8 +190,7 @@ module ActionView
virtual_path: path.virtual,
format: format,
variant: variant,
- locals: locals,
- updated_at: mtime(template)
+ locals: locals
)
end
end
@@ -272,11 +243,6 @@ module ActionView
entry.gsub(/[*?{}\[\]]/, '\\\\\\&')
end
- # Returns the file mtime from the filesystem.
- def mtime(p)
- File.mtime(p)
- end
-
# Extract handler, formats and variant from path. If a format cannot be found neither
# from the path, or the handler, we should return the array of formats given
# to the resolver.
diff --git a/actionview/lib/action_view/testing/resolvers.rb b/actionview/lib/action_view/testing/resolvers.rb
index 3ca8420c6c..a16dc0096e 100644
--- a/actionview/lib/action_view/testing/resolvers.rb
+++ b/actionview/lib/action_view/testing/resolvers.rb
@@ -31,16 +31,14 @@ module ActionView #:nodoc:
query = /^(#{Regexp.escape(path)})#{query}$/
templates = []
- @hash.each do |_path, array|
- source, updated_at = array
+ @hash.each do |_path, source|
next unless query.match?(_path)
handler, format, variant = extract_handler_and_format_and_variant(_path)
templates << Template.new(source, _path, handler,
virtual_path: path.virtual,
format: format,
variant: variant,
- locals: locals,
- updated_at: updated_at
+ locals: locals
)
end
diff --git a/actionview/test/template/digestor_test.rb b/actionview/test/template/digestor_test.rb
index 7affd3c005..4515afdfff 100644
--- a/actionview/test/template/digestor_test.rb
+++ b/actionview/test/template/digestor_test.rb
@@ -326,12 +326,14 @@ class TemplateDigestorTest < ActionView::TestCase
def assert_digest_difference(template_name, options = {})
previous_digest = digest(template_name, options)
+ finder.view_paths.each(&:clear_cache)
finder.digest_cache.clear
yield
assert_not_equal previous_digest, digest(template_name, options), "digest didn't change"
finder.digest_cache.clear
+ finder.view_paths.each(&:clear_cache)
end
def digest(template_name, options = {})
diff --git a/actionview/test/template/lookup_context_test.rb b/actionview/test/template/lookup_context_test.rb
index 62935620e9..537f8ee163 100644
--- a/actionview/test/template/lookup_context_test.rb
+++ b/actionview/test/template/lookup_context_test.rb
@@ -235,56 +235,6 @@ class LookupContextTest < ActiveSupport::TestCase
end
end
-class LookupContextWithFalseCaching < ActiveSupport::TestCase
- def setup
- @resolver = ActionView::FixtureResolver.new("test/_foo.erb" => ["Foo", Time.utc(2000)])
- @lookup_context = ActionView::LookupContext.new(@resolver, {})
- end
-
- test "templates are always found in the resolver but timestamp is checked before being compiled" do
- ActionView::Resolver.stub(:caching?, false) do
- template = @lookup_context.find("foo", %w(test), true)
- assert_equal "Foo", template.source
-
- # Now we are going to change the template, but it won't change the returned template
- # since the timestamp is the same.
- @resolver.data["test/_foo.erb"][0] = "Bar"
- template = @lookup_context.find("foo", %w(test), true)
- assert_equal "Foo", template.source
-
- # Now update the timestamp.
- @resolver.data["test/_foo.erb"][1] = Time.now.utc
- template = @lookup_context.find("foo", %w(test), true)
- assert_equal "Bar", template.source
- end
- end
-
- test "if no template was found in the second lookup, with no cache, raise error" do
- ActionView::Resolver.stub(:caching?, false) do
- template = @lookup_context.find("foo", %w(test), true)
- assert_equal "Foo", template.source
-
- @resolver.data.clear
- assert_raise ActionView::MissingTemplate do
- @lookup_context.find("foo", %w(test), true)
- end
- end
- end
-
- test "if no template was cached in the first lookup, retrieval should work in the second call" do
- ActionView::Resolver.stub(:caching?, false) do
- @resolver.data.clear
- assert_raise ActionView::MissingTemplate do
- @lookup_context.find("foo", %w(test), true)
- end
-
- @resolver.data["test/_foo.erb"] = ["Foo", Time.utc(2000)]
- template = @lookup_context.find("foo", %w(test), true)
- assert_equal "Foo", template.source
- end
- end
-end
-
class TestMissingTemplate < ActiveSupport::TestCase
def setup
@lookup_context = ActionView::LookupContext.new("/Path/to/views", {})
diff --git a/activerecord/lib/active_record/insert_all.rb b/activerecord/lib/active_record/insert_all.rb
index 5baaea344b..3833cb2fcf 100644
--- a/activerecord/lib/active_record/insert_all.rb
+++ b/activerecord/lib/active_record/insert_all.rb
@@ -92,7 +92,15 @@ module ActiveRecord
def values_list
columns = connection.schema_cache.columns_hash(model.table_name)
+
+ column_names = columns.keys.to_set
keys = insert_all.keys.to_set
+ unknown_columns = keys - column_names
+
+ unless unknown_columns.empty?
+ raise UnknownAttributeError.new(model.new, unknown_columns.first)
+ end
+
types = keys.map { |key| [ key, connection.lookup_cast_type_from_column(columns[key]) ] }.to_h
values_list = insert_all.inserts.map do |attributes|
diff --git a/activerecord/test/cases/insert_all_test.rb b/activerecord/test/cases/insert_all_test.rb
index 63245719c0..a3e920969d 100644
--- a/activerecord/test/cases/insert_all_test.rb
+++ b/activerecord/test/cases/insert_all_test.rb
@@ -136,4 +136,10 @@ class InsertAllTest < ActiveRecord::TestCase
assert_equal ["Out of the Silent Planet", "Perelandra"], Book.where(isbn: "1974522598").order(:name).pluck(:name)
end
+
+ def test_insert_all_raises_on_unknown_attribute
+ assert_raise ActiveRecord::UnknownAttributeError do
+ Book.insert_all! [{ unknown_attribute: "Test" }]
+ end
+ end
end
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 2610cc63a4..b2330f2c9d 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,3 +1,7 @@
+* In Zeitwerk mode, engines are now managed by the `main` autoloader. Engines may reference application constants, if the application is reloaded and we do not reload engines, they won't use the reloaded application code.
+
+ *Xavier Noria*
+
* Add support for supplying `locale` to `transliterate` and `parameterize`.
I18n.backend.store_translations(:de, i18n: { transliterate: { rule: { "ü" => "ue" } } })
diff --git a/activesupport/lib/active_support/core_ext/string/inflections.rb b/activesupport/lib/active_support/core_ext/string/inflections.rb
index e63b38b227..5eb8d9f99b 100644
--- a/activesupport/lib/active_support/core_ext/string/inflections.rb
+++ b/activesupport/lib/active_support/core_ext/string/inflections.rb
@@ -165,7 +165,7 @@ class String
# If the optional parameter +locale+ is specified,
# the word will be parameterized as a word of that language.
# By default, this parameter is set to <tt>nil</tt> and it will use
- # configured I18n.locale
+ # the configured <tt>I18n.locale</tt>.
#
# class Person
# def to_param
diff --git a/activesupport/lib/active_support/dependencies/zeitwerk_integration.rb b/activesupport/lib/active_support/dependencies/zeitwerk_integration.rb
index 1e697e1ba5..e00307d257 100644
--- a/activesupport/lib/active_support/dependencies/zeitwerk_integration.rb
+++ b/activesupport/lib/active_support/dependencies/zeitwerk_integration.rb
@@ -71,8 +71,7 @@ module ActiveSupport
end
def autoload_once?(autoload_path)
- Dependencies.autoload_once_paths.include?(autoload_path) ||
- Gem.path.any? { |gem_path| autoload_path.to_s.start_with?(gem_path) }
+ Dependencies.autoload_once_paths.include?(autoload_path)
end
def freeze_autoload_paths
diff --git a/activesupport/lib/active_support/evented_file_update_checker.rb b/activesupport/lib/active_support/evented_file_update_checker.rb
index 54bc5c0ae5..3893b0de0e 100644
--- a/activesupport/lib/active_support/evented_file_update_checker.rb
+++ b/activesupport/lib/active_support/evented_file_update_checker.rb
@@ -131,7 +131,9 @@ module ActiveSupport
ext = @ph.normalize_extension(file.extname)
file.dirname.ascend do |dir|
- if @dirs.fetch(dir, []).include?(ext)
+ matching = @dirs[dir]
+
+ if matching && (matching.empty? || matching.include?(ext))
break true
elsif dir == @lcsp || dir.root?
break false
diff --git a/activesupport/lib/active_support/inflector/transliterate.rb b/activesupport/lib/active_support/inflector/transliterate.rb
index fe778ff0e7..ec6e9ccb59 100644
--- a/activesupport/lib/active_support/inflector/transliterate.rb
+++ b/activesupport/lib/active_support/inflector/transliterate.rb
@@ -74,8 +74,8 @@ module ActiveSupport
#
# To use a custom separator, override the +separator+ argument.
#
- # parameterize("Donald E. Knuth", separator: '_') # => "donald_e_knuth"
- # parameterize("^très|Jolie__ ", separator: '_') # => "tres_jolie"
+ # parameterize("Donald E. Knuth", separator: '_') # => "donald_e_knuth"
+ # parameterize("^très|Jolie__ ", separator: '_') # => "tres_jolie"
#
# To preserve the case of the characters in a string, use the +preserve_case+ argument.
#
@@ -84,10 +84,14 @@ module ActiveSupport
#
# It preserves dashes and underscores unless they are used as separators:
#
- # parameterize("^très|Jolie__ ") # => "tres-jolie__"
- # parameterize("^très|Jolie-- ", separator: "_") # => "tres_jolie--"
- # parameterize("^très_Jolie-- ", separator: ".") # => "tres_jolie--"
+ # parameterize("^très|Jolie__ ") # => "tres-jolie__"
+ # parameterize("^très|Jolie-- ", separator: "_") # => "tres_jolie--"
+ # parameterize("^très_Jolie-- ", separator: ".") # => "tres_jolie--"
#
+ # If the optional parameter +locale+ is specified,
+ # the word will be parameterized as a word of that language.
+ # By default, this parameter is set to <tt>nil</tt> and it will use
+ # the configured <tt>I18n.locale<tt>.
def parameterize(string, separator: "-", preserve_case: false, locale: nil)
# Replace accented chars with their ASCII equivalents.
parameterized_string = transliterate(string, locale: locale)
diff --git a/activesupport/test/file_update_checker_shared_tests.rb b/activesupport/test/file_update_checker_shared_tests.rb
index 72683816b3..84d89fa0a7 100644
--- a/activesupport/test/file_update_checker_shared_tests.rb
+++ b/activesupport/test/file_update_checker_shared_tests.rb
@@ -186,6 +186,18 @@ module FileUpdateCheckerSharedTests
assert_equal 1, i
end
+ test "should execute the block if files change in a watched directory any extensions" do
+ i = 0
+
+ checker = new_checker([], tmpdir => []) { i += 1 }
+
+ touch(tmpfile("foo.rb"))
+ wait
+
+ assert checker.execute_if_updated
+ assert_equal 1, i
+ end
+
test "should execute the block if files change in a watched directory several extensions" do
i = 0
diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md
index 24dea0ec46..4675730bd0 100644
--- a/guides/source/active_record_querying.md
+++ b/guides/source/active_record_querying.md
@@ -1731,10 +1731,13 @@ Client.find_by_sql("SELECT * FROM clients
### `select_all`
-`find_by_sql` has a close relative called `connection#select_all`. `select_all` will retrieve objects from the database using custom SQL just like `find_by_sql` but will not instantiate them. This method will return an instance of `ActiveRecord::Result` class and calling `to_hash` on this object would return you an array of hashes where each hash indicates a record.
+`find_by_sql` has a close relative called `connection#select_all`. `select_all` will retrieve
+objects from the database using custom SQL just like `find_by_sql` but will not instantiate them.
+This method will return an instance of `ActiveRecord::Result` class and calling `to_a` on this
+object would return you an array of hashes where each hash indicates a record.
```ruby
-Client.connection.select_all("SELECT first_name, created_at FROM clients WHERE id = '1'").to_hash
+Client.connection.select_all("SELECT first_name, created_at FROM clients WHERE id = '1'").to_a
# => [
# {"first_name"=>"Rafael", "created_at"=>"2012-11-10 23:23:45.281189"},
# {"first_name"=>"Eileen", "created_at"=>"2013-12-09 11:22:35.221282"}
diff --git a/railties/lib/rails/command/environment_argument.rb b/railties/lib/rails/command/environment_argument.rb
index fdc5ee92d9..0cb3f1ce1e 100644
--- a/railties/lib/rails/command/environment_argument.rb
+++ b/railties/lib/rails/command/environment_argument.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require "active_support"
+require "active_support/core_ext/class/attribute"
module Rails
module Command
@@ -8,16 +9,16 @@ module Rails
extend ActiveSupport::Concern
included do
- class_option :environment, aliases: "-e", type: :string,
- desc: "Specifies the environment to run this console under (test/development/production)."
+ class_attribute :environment_desc, default: "Specifies the environment to run this #{self.command_name} under (test/development/production)."
+ class_option :environment, aliases: "-e", type: :string, desc: environment_desc
end
private
- def extract_environment_option_from_argument
+ def extract_environment_option_from_argument(default_environment: Rails::Command.environment)
if options[:environment]
self.options = options.merge(environment: acceptable_environment(options[:environment]))
else
- self.options = options.merge(environment: Rails::Command.environment)
+ self.options = options.merge(environment: default_environment)
end
end
diff --git a/railties/lib/rails/commands/credentials/credentials_command.rb b/railties/lib/rails/commands/credentials/credentials_command.rb
index 54ccd97506..a22b1f3f84 100644
--- a/railties/lib/rails/commands/credentials/credentials_command.rb
+++ b/railties/lib/rails/commands/credentials/credentials_command.rb
@@ -2,14 +2,15 @@
require "active_support"
require "rails/command/helpers/editor"
+require "rails/command/environment_argument"
module Rails
module Command
class CredentialsCommand < Rails::Command::Base # :nodoc:
include Helpers::Editor
+ include EnvironmentArgument
- class_option :environment, aliases: "-e", type: :string,
- desc: "Uses credentials from config/credentials/:environment.yml.enc encrypted by config/credentials/:environment.key key"
+ self.environment_desc = "Uses credentials from config/credentials/:environment.yml.enc encrypted by config/credentials/:environment.key key"
no_commands do
def help
@@ -20,6 +21,7 @@ module Rails
end
def edit
+ extract_environment_option_from_argument(default_environment: nil)
require_application!
ensure_editor_available(command: "bin/rails credentials:edit") || (return)
@@ -37,6 +39,7 @@ module Rails
end
def show
+ extract_environment_option_from_argument(default_environment: nil)
require_application!
say credentials.read.presence || missing_credentials_message
diff --git a/railties/lib/rails/commands/runner/runner_command.rb b/railties/lib/rails/commands/runner/runner_command.rb
index cb693bcf34..40fb5e4d89 100644
--- a/railties/lib/rails/commands/runner/runner_command.rb
+++ b/railties/lib/rails/commands/runner/runner_command.rb
@@ -1,11 +1,13 @@
# frozen_string_literal: true
+require "rails/command/environment_argument"
+
module Rails
module Command
class RunnerCommand < Base # :nodoc:
- class_option :environment, aliases: "-e", type: :string,
- default: Rails::Command.environment.dup,
- desc: "The environment for the runner to operate under (test/development/production)"
+ include EnvironmentArgument
+
+ self.environment_desc = "The environment for the runner to operate under (test/development/production)"
no_commands do
def help
@@ -19,6 +21,8 @@ module Rails
end
def perform(code_or_file = nil, *command_argv)
+ extract_environment_option_from_argument
+
unless code_or_file
help
exit 1
diff --git a/railties/lib/rails/commands/server/server_command.rb b/railties/lib/rails/commands/server/server_command.rb
index 43f7b76fd6..982b83ead5 100644
--- a/railties/lib/rails/commands/server/server_command.rb
+++ b/railties/lib/rails/commands/server/server_command.rb
@@ -6,6 +6,7 @@ require "rails"
require "active_support/deprecation"
require "active_support/core_ext/string/filters"
require "rails/dev_caching"
+require "rails/command/environment_argument"
module Rails
class Server < ::Rack::Server
@@ -91,6 +92,8 @@ module Rails
module Command
class ServerCommand < Base # :nodoc:
+ include EnvironmentArgument
+
# Hard-coding a bunch of handlers here as we don't have a public way of
# querying them from the Rack::Handler registry.
RACK_SERVERS = %w(cgi fastcgi webrick lsws scgi thin puma unicorn)
@@ -109,8 +112,6 @@ module Rails
desc: "Uses a custom rackup configuration.", banner: :file
class_option :daemon, aliases: "-d", type: :boolean, default: false,
desc: "Runs server as a Daemon."
- class_option :environment, aliases: "-e", type: :string,
- desc: "Specifies the environment to run this server under (development/test/production).", banner: :name
class_option :using, aliases: "-u", type: :string,
desc: "Specifies the Rack server used to run the application (thin/puma/webrick).", banner: :name
class_option :pid, aliases: "-P", type: :string, default: DEFAULT_PID_PATH,
@@ -130,6 +131,7 @@ module Rails
end
def perform
+ extract_environment_option_from_argument
set_application_directory!
prepare_restart
diff --git a/railties/test/application/runner_test.rb b/railties/test/application/runner_test.rb
index d590b6f6fb..dfb9540093 100644
--- a/railties/test/application/runner_test.rb
+++ b/railties/test/application/runner_test.rb
@@ -109,6 +109,10 @@ module ApplicationTests
assert_match "production", rails("runner", "-e", "production", "puts Rails.env")
end
+ def test_environment_option_is_properly_expanded
+ assert_match "production", rails("runner", "-e", "prod", "puts Rails.env")
+ end
+
def test_runner_detects_syntax_errors
output = rails("runner", "puts 'hello world", allow_failure: true)
assert_not_predicate $?, :success?
diff --git a/railties/test/application/zeitwerk_integration_test.rb b/railties/test/application/zeitwerk_integration_test.rb
index cddbf5a22d..c82b37d07d 100644
--- a/railties/test/application/zeitwerk_integration_test.rb
+++ b/railties/test/application/zeitwerk_integration_test.rb
@@ -149,22 +149,27 @@ class ZeitwerkIntegrationTest < ActiveSupport::TestCase
assert $zeitwerk_integration_test_extras
end
- test "autoload paths that are below Gem.path go to the once autoloader" do
- app_dir "extras"
- add_to_config 'config.autoload_paths << "#{Rails.root}/extras"'
-
- # Mocks Gem.path to include the extras directory.
- Gem.singleton_class.prepend(
- Module.new do
- def path
- super + ["#{Rails.root}/extras"]
- end
- end
- )
+ test "autoload_paths are set as root dirs of main, and in the same order" do
boot
- assert_not_includes Rails.autoloaders.main.dirs, "#{app_path}/extras"
- assert_includes Rails.autoloaders.once.dirs, "#{app_path}/extras"
+ existing_autoload_paths = deps.autoload_paths.select { |dir| File.directory?(dir) }
+ assert_equal existing_autoload_paths, Rails.autoloaders.main.dirs
+ end
+
+ test "autoload_once_paths go to the once autoloader, and in the same order" do
+ extras = %w(e1 e2 e3)
+ extras.each do |extra|
+ app_dir extra
+ add_to_config %(config.autoload_once_paths << "\#{Rails.root}/#{extra}")
+ end
+
+ boot
+
+ extras = extras.map { |extra| "#{app_path}/#{extra}" }
+ extras.each do |extra|
+ assert_not_includes Rails.autoloaders.main.dirs, extra
+ end
+ assert_equal extras, Rails.autoloaders.once.dirs
end
test "clear reloads the main autoloader, and does not reload the once one" do
diff --git a/railties/test/commands/credentials_test.rb b/railties/test/commands/credentials_test.rb
index 10d0ba1cae..3654e96aed 100644
--- a/railties/test/commands/credentials_test.rb
+++ b/railties/test/commands/credentials_test.rb
@@ -63,6 +63,14 @@ class Rails::Command::CredentialsCommandTest < ActiveSupport::TestCase
end
end
+ test "edit command properly expand environment option" do
+ assert_match(/access_key_id: 123/, run_edit_command(environment: "prod"))
+ Dir.chdir(app_path) do
+ assert File.exist?("config/credentials/production.key")
+ assert File.exist?("config/credentials/production.yml.enc")
+ end
+ end
+
test "edit command does not raise when an initializer tries to access non-existent credentials" do
app_file "config/initializers/raise_when_loaded.rb", <<-RUBY
Rails.application.credentials.missing_key!
@@ -95,6 +103,12 @@ class Rails::Command::CredentialsCommandTest < ActiveSupport::TestCase
assert_match(/access_key_id: 123/, run_show_command(environment: "production"))
end
+ test "show command properly expand environment option" do
+ run_edit_command(environment: "production")
+
+ assert_match(/access_key_id: 123/, run_show_command(environment: "prod"))
+ end
+
private
def run_edit_command(editor: "cat", environment: nil, **options)
switch_env("EDITOR", editor) do
diff --git a/railties/test/commands/server_test.rb b/railties/test/commands/server_test.rb
index 25b89ecbd8..b78370a233 100644
--- a/railties/test/commands/server_test.rb
+++ b/railties/test/commands/server_test.rb
@@ -22,6 +22,12 @@ class Rails::Command::ServerCommandTest < ActiveSupport::TestCase
assert_nil options[:server]
end
+ def test_environment_option_is_properly_expanded
+ args = ["-e", "prod"]
+ options = parse_arguments(args)
+ assert_equal "production", options[:environment]
+ end
+
def test_explicit_using_option
args = ["-u", "thin"]
options = parse_arguments(args)
@@ -285,6 +291,8 @@ class Rails::Command::ServerCommandTest < ActiveSupport::TestCase
end
def parse_arguments(args = [])
- Rails::Command::ServerCommand.new([], args).server_options
+ command = Rails::Command::ServerCommand.new([], args)
+ command.send(:extract_environment_option_from_argument)
+ command.server_options
end
end