Project

General

Profile

Actions

Feature #19521

closed

Support for `Module#name=` and `Class#name=`.

Added by ioquatix (Samuel Williams) over 1 year ago. Updated over 1 year ago.

Status:
Closed
Assignee:
-
Target version:
-
[ruby-core:112773]

Description

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

This proposal introduces Module#name= (and thus also Class#name=) to set the temporary class name. The name assignment has no effect if the module/class already has a permanent name.

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

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

Alternatively, we could use set_name:

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:

  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:

  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.


Related issues 3 (0 open3 closed)

Related to Ruby master - Feature #19520: Support for `Module.new(name)` and `Class.new(superclass, name)`.RejectedActions
Related to Ruby master - Feature #19450: Is there an official way to set a class name without setting a constant?ClosedActions
Related to Ruby master - Bug #20892: `ObjectSpace.dump` can produce broken JSON for classes with temporary namesClosedActions
Actions

Also available in: Atom PDF

Like3
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like1Like0Like0