Skip to content

Commit 265bfad

Browse files
committed
Raise if setting a config key that is a method name
1 parent c396f20 commit 265bfad

File tree

4 files changed

+72
-1
lines changed

4 files changed

+72
-1
lines changed

railties/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
* Trying to set a config key with the same name of a method now raises:
2+
3+
```ruby
4+
config.load_defaults = 7.0
5+
# NoMethodError: Cannot assign to `load_defaults`, it is a configuration method
6+
```
7+
8+
*Xavier Noria*
9+
110
* Deprecate `secrets:edit/show` and remove `secrets:setup`
211

312
`bin/rails secrets:setup` has been deprecated since Rails 5.2 in favor of

railties/lib/rails/railtie/configuration.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,17 @@ def respond_to?(name, include_private = false)
9292
end
9393

9494
private
95+
def actual_method?(key)
96+
!@@options.key?(key) && respond_to?(key)
97+
end
98+
9599
def method_missing(name, *args, &blk)
96100
if name.end_with?("=")
97-
@@options[:"#{name[0..-2]}"] = args.first
101+
key = name[0..-2].to_sym
102+
if actual_method?(key)
103+
raise NoMethodError.new("Cannot assign to `#{key}`, it is a configuration method")
104+
end
105+
@@options[key] = args.first
98106
elsif @@options.key?(name)
99107
@@options[name]
100108
else

railties/test/application/configuration_test.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4371,6 +4371,17 @@ def new(app); self; end
43714371
assert_equal true, ActiveRecord.run_after_transaction_callbacks_in_order_defined
43724372
end
43734373

4374+
test "raises if configuration tries to assign to an actual method" do
4375+
remove_from_config '.*config\.load_defaults.*\n'
4376+
add_to_config 'config.load_defaults = "7.0"'
4377+
4378+
error = assert_raises(NoMethodError) do
4379+
app "development"
4380+
end
4381+
4382+
assert_match(/Cannot assign to `load_defaults`, it is a configuration method/, error.message)
4383+
end
4384+
43744385
private
43754386
def set_custom_config(contents, config_source = "custom".inspect)
43764387
app_file "config/custom.yml", contents
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# frozen_string_literal: true
2+
3+
require "active_support"
4+
require "active_support/test_case"
5+
require "active_support/testing/autorun"
6+
require "rails/railtie/configuration"
7+
8+
module RailtiesTest
9+
class DynamicOptionsTest < ActiveSupport::TestCase
10+
class Configuration < Rails::Railtie::Configuration
11+
def reset_options
12+
@@options = {}
13+
end
14+
end
15+
16+
setup do
17+
@config = Configuration.new
18+
@config.reset_options
19+
end
20+
21+
test "arbitrary keys can be set, reset, and read" do
22+
@config.foo = 1
23+
assert_equal 1, @config.foo
24+
25+
@config.foo = 2
26+
assert_equal 2, @config.foo
27+
end
28+
29+
test "raises NoMethodError if the key is unset and the method does not exist" do
30+
assert_raises(NoMethodError) do
31+
@config.unset_key
32+
end
33+
end
34+
35+
test "raises NoMethodError with an informative message if assigning to an existing method" do
36+
error = assert_raises(NoMethodError) do
37+
@config.eager_load_namespaces = 1
38+
end
39+
40+
assert_match(/Cannot assign to `eager_load_namespaces`, it is a configuration method/, error.message)
41+
end
42+
end
43+
end

0 commit comments

Comments
 (0)