Raise `ArgumentError` when reading from `config.x` with arguments

The flexibility provided by `config.x` supports arbitrarily defining new
configuration objects on-the-fly. Each new intermediate configuration
object is constructed during chaining from its ancestor through a method
invocation made without arguments.

Conversely, writing to leaf configuration values occurs when the invoked
method's name ends with `=`, and the new configuration value is assigned
to whatever that method's arguments are.

There are no cases when reading from a `config.x` value or building the
intermediate values involves arguments.

Prior to this commit, a read invoked with a method arguments would
ignore those arguments. While this is robust and error-free, it's
possible to obscure misuse.

For example, consider a line like:

```ruby
config.x.my_config.enabled = true
config.x.my_config.enabled #=> true
```

Now consider that first line with a typo that omits the `=`:

```ruby
config.x.my_config.enabled true
config.x.my_config.enabled #=> nil
```

This commit aims to provide more direct feedback for scenarios like the
one above. There aren't legitimate use cases for invoking `#enabled`
with arguments, so raise a `ArgumentError` when encountering a read with
arguments.
This commit is contained in:
Sean Doyle 2023-11-13 19:20:21 -05:00
parent b1fd934bbc
commit 9a58f7eccd
3 changed files with 17 additions and 1 deletions

View File

@ -1,3 +1,11 @@
* Raise `ArgumentError` when reading `config.x.something` with arguments
```ruby
config.x.this_works.this_raises true # raises ArgumentError
```
*Sean Doyle*
* Add default PWA files for manifest and service-worker that are served from `app/views/pwa` and can be dynamically rendered through erb. Mount these files explicitly at the root with default routes in the generated routes file.
*DHH*

View File

@ -569,10 +569,14 @@ module Rails
def method_missing(method, *args)
if method.end_with?("=")
@configurations[:"#{method[0..-2]}"] = args.first
else
elsif args.none?
@configurations.fetch(method) {
@configurations[method] = ActiveSupport::OrderedOptions.new
}
else
arguments = args.map(&:inspect)
raise ArgumentError.new("unexpected arguments (%s) while reading `%s` configuration" % [arguments.join(", "), method])
end
end

View File

@ -36,6 +36,10 @@ module ApplicationTests
assert_respond_to x, :i_do_not_exist
assert_kind_of Method, x.method(:i_do_not_exist)
assert_kind_of ActiveSupport::OrderedOptions, x.i_do_not_exist
assert_raises ArgumentError, match: "unexpected arguments (true, false) while reading `i_do_not_exist` configuration" do
x.i_do_not_exist(true, false)
end
end
private