Project

General

Profile

Feature #19521

Updated by ioquatix (Samuel Williams) about 1 year ago

See https://bugs.ruby-lang.org/issues/19450 for previous discussion and motivation. 

 [This proposal](https://github.com/ruby/ruby/pull/7483) introduces `Module#name=` (and thus also `Class#name=`) `Class#name`) to set the temporary class name. The name assignment has no effect if the module/class already has a permanent name. 

 ```ruby 
 c = Class.new do 
   self.name = "fake name" 
 end 

 c = Class.new 
 c.name = "fake name" 
 ``` 

 Alternatively, we could use `set_name`: 

 ```ruby 
 Class.new do 
   set_name "fake_name" 
 end 
 ``` 

 Setting the name of a class changes its current name, irrespective of whether it's been assigned a permanent name, or has nested modules/classes which have cached a previous name. We might like to limit the cases where a name is set, e.g. only once, only if the name is nil, or only if it's not already permanent. There is no real harm in any of those options, just inconsistency. 

 ## Example usage 

 The current Ruby test suite has code which shows the usefulness of this new method: 

 ```ruby 
   def labeled_module(name, &block) 
     Module.new do 
       singleton_class.class_eval { 
         define_method(:to_s) {name} 
         alias inspect to_s 
         alias name to_s 
       } 
       class_eval(&block) if block 
     end 
   end 
   module_function :labeled_module 

   def labeled_class(name, superclass = Object, &block) 
     Class.new(superclass) do 
       singleton_class.class_eval { 
         define_method(:to_s) {name} 
         alias inspect to_s 
         alias name to_s 
       } 
       class_eval(&block) if block 
     end 
   end 
   module_function :labeled_class 
 ``` 

 The updated code would look like this: 

 ```ruby 
   def labeled_module(name, &block) 
     Module.new do 
       self.name = name 
       class_eval(&block) if block 
     end 
   end 

   def labeled_class(name, superclass = Object, &block) 
     Class.new(superclass) do 
       self.name = name 
       class_eval(&block) if block 
     end 
   end 
   module_function :labeled_class 
 ``` 

 Because the name cannot be set as part of `.new`, we have to have a separate block to set the name, before calling `class_eval`. I think the ergonomics and performance of this are slightly worse than the [counter proposal](https://bugs.ruby-lang.org/issues/19520).

Back