Merge pull request #48030 from rails/config

Raise if setting a config key that is a method name
This commit is contained in:
Xavier Noria 2023-04-23 10:38:34 +02:00 committed by GitHub
commit ea7ac1594b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 72 additions and 1 deletions

@ -1,3 +1,12 @@
* Trying to set a config key with the same name of a method now raises:
```ruby
config.load_defaults = 7.0
# NoMethodError: Cannot assign to `load_defaults`, it is a configuration method
```
*Xavier Noria*
* Deprecate `secrets:edit/show` and remove `secrets:setup`
`bin/rails secrets:setup` has been deprecated since Rails 5.2 in favor of

@ -92,9 +92,17 @@ def respond_to?(name, include_private = false)
end
private
def actual_method?(key)
!@@options.key?(key) && respond_to?(key)
end
def method_missing(name, *args, &blk)
if name.end_with?("=")
@@options[:"#{name[0..-2]}"] = args.first
key = name[0..-2].to_sym
if actual_method?(key)
raise NoMethodError.new("Cannot assign to `#{key}`, it is a configuration method")
end
@@options[key] = args.first
elsif @@options.key?(name)
@@options[name]
else

@ -4371,6 +4371,17 @@ def new(app); self; end
assert_equal true, ActiveRecord.run_after_transaction_callbacks_in_order_defined
end
test "raises if configuration tries to assign to an actual method" do
remove_from_config '.*config\.load_defaults.*\n'
add_to_config 'config.load_defaults = "7.0"'
error = assert_raises(NoMethodError) do
app "development"
end
assert_match(/Cannot assign to `load_defaults`, it is a configuration method/, error.message)
end
private
def set_custom_config(contents, config_source = "custom".inspect)
app_file "config/custom.yml", contents

@ -0,0 +1,43 @@
# frozen_string_literal: true
require "active_support"
require "active_support/test_case"
require "active_support/testing/autorun"
require "rails/railtie/configuration"
module RailtiesTest
class DynamicOptionsTest < ActiveSupport::TestCase
class Configuration < Rails::Railtie::Configuration
def reset_options
@@options = {}
end
end
setup do
@config = Configuration.new
@config.reset_options
end
test "arbitrary keys can be set, reset, and read" do
@config.foo = 1
assert_equal 1, @config.foo
@config.foo = 2
assert_equal 2, @config.foo
end
test "raises NoMethodError if the key is unset and the method does not exist" do
assert_raises(NoMethodError) do
@config.unset_key
end
end
test "raises NoMethodError with an informative message if assigning to an existing method" do
error = assert_raises(NoMethodError) do
@config.eager_load_namespaces = 1
end
assert_match(/Cannot assign to `eager_load_namespaces`, it is a configuration method/, error.message)
end
end
end