Alexey
Alexey

Reputation: 9447

How to "import" nested classes into current class in Ruby?

In Ruby I can nest modules/classes into other modules/classes. What I want is to add some declaration inside file or class to be able to refer nested classes by their short names, e.g. to use Inner to get Outer::Inner, like you would have in Java, C# etc. The syntax might be like this:

module Outer
  class Inner; end
  class AnotherInner; end
end
class C
  import Outer: [:Inner, :AnotherInner]
  def f
    Inner
  end
end

The simplistic implementation could be like this:

class Class
  def import(constants)
    @imported_constants = 
      (@imported_constants || {}).merge Hash[
        constants.flat_map { |namespace, names|
          [*names].map { |name| [name.to_sym, "#{namespace}::#{name}"] }
        }]
  end

  def const_missing(name)
    const_set name, eval(@imported_constants[name] || raise)
  end
end

Is there solid implementation in Rails or some gem, that does similar importing while compatible with Rails' mechanism of auto-loading?

Upvotes: 6

Views: 1804

Answers (1)

Jörg W Mittag
Jörg W Mittag

Reputation: 369498

module Outer
  class Inner; end
  class AnotherInner; end
end

class C
  include Outer

  def f
    Inner
  end
end

C.new.f # => Outer::Inner

Remember: there is no such thing as a nested class in Ruby. A class is just an object like any other object, and it gets assigned to variables just like any other. In this particular case, the "variable" is a constant which is namespaced inside a module. And you add that constant to the namespace of another module (or class) the same way you would any other constant: by includeing the module.

Upvotes: 2

Related Questions