
Issue #20993 has been reported by byroot (Jean Boussier). ---------------------------------------- Feature #20993: Allow `class <constant-path> = <expression>` syntax https://bugs.ruby-lang.org/issues/20993 * Author: byroot (Jean Boussier) * Status: Open ---------------------------------------- This is meant as a solution for: https://bugs.ruby-lang.org/issues/20943 ## Context When using `Struct.new` or `Data.define`, you often see one of these patterns: ```ruby class MyStruct < Struct.new(:foo, :bar) # ... end ``` Or: ```ruby MyStruct = Struct.new(:foo, :bar) do # ... end ``` The first one is OK, but not ideal because `MyStruct` inherits from an anonymous class. That's not that big of a deal, but it's an extra, generally useless class: ```ruby
MyClass.ancestors => [MyClass, #<Class:0x000000012a811548>, Struct, ...]
The second one is OK too, but can lead to two mistakes.
First, since it doesn't create a nesting, if you assign a constant, it won't be set where you expect it.
```ruby
MyStruct = Struct.new(:foo) do
BAR = 1 # This sets Object::BAR, not MyStruct::BAR
end
The second potential issue is that the class only get named after the block complete, so some `inherited` or `included` hooks that rely on the class name may break. ## Proposal The "ideal" way to define a `Struct` or `Data` would be: ```ruby MyStruct = Struct.new(:foo, :bar) class MyStruct # body end ``` But it's a bit awkward. Given that `class <constant-path> < <expression>` is valid, this makes me think we could also accept `class <constant-path> = <expression>` such as: ```ruby class MyStruct = Struct.new(:foo, :bar) # body end ``` Would be valid syntax and the recommended way to define `Struct` and `Data` classes. Of course `module <constant-path> = <expression>` would be valid as well. If the expression doesn't return the expected type (either `Class` or `Module`), it would raise a `TypeError`. -- https://bugs.ruby-lang.org/