Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby: Is there a way to get the enclosing Module const of a Class?

I'm doing some metaprogramming in Ruby, and I need to dynamically generate a sibling class inside of a module. In doing so, I want to call const_set on the module, but I don't know which Module constant to call that on until runtime. An example:

Given classes

Foo::Bar::Baz
Foo::Quox::Quack

I want to be able to call a function like this (oversimplified here):

def generate_from klass
  mod = klass.enclosing_module # <- THIS LINE is the one I need to figure out
  mod.const_set("GeneratedClassName", Class.new)
end

and what I want to end up with, when calling with Baz, is a new class defined as

Foo::Bar::GeneratedClassName

and with a Quack, I want

Foo::Quox::GeneratedClassName

The only way I know of is to split up klass.name, then repeatedly call const_get on those strings, constantized. Does anyone know of a more elegant way?

like image 504
Matt Avatar asked Jun 01 '11 21:06

Matt


People also ask

How do you access a module method in Ruby?

To access the instance method defined inside the module, the user has to include the module inside a class and then use the class instance to access that method.

How do you reference a module in Ruby?

As with class methods, you call a module method by preceding its name with the module's name and a period, and you reference a constant using the module name and two colons.

Can we define module inside class Ruby?

You can define and access instance variables within a module's instance methods, but you can't actually instantiate a module. A module's instance variables exist only within objects of a class that includes the module.

Can modules inherit Ruby?

The Ruby class Class inherits from Module and adds things like instantiation, properties, etc – all things you would normally think a class would have. Because Module is literally an ancestor of Class , this means Modules can be treated like classes in some ways.


1 Answers

In case anyone is looking for a pure ruby version:

  def get_parent_type
    #Note: This will break for base types (lacking '::' in the name)
    parent_type=self.class.name.split('::')[0...-1]
    begin
      Object.const_get(parent_type.join('::'))
    rescue NameError => e
      nil
    end
  end
like image 137
jwood Avatar answered Sep 28 '22 06:09

jwood