I am using a library that doesn't handle namespaced models. I have a rails engine that has all the ActiveRecord models that I need to use and as such I reference them with the namespace of the engine, ex: TableEngine::Posts.
Is there a way in Ruby to un-namespace the Posts class?
something like
TableEngine::Posts.demodulize # => Posts
At first you can add the constant you need and assign the Class/Module to it (remember both are just objects). You should duplicate it to reset the name:
Posts = TableEngine::Posts.dup
Afterwards remove the source constant name:
Object.send :remove_const, :TableEngine
Then:
Posts
# => Posts
TableEngine
# => NameError: uninitialized constant TableEngine
TableEngine::Posts
# => NameError: uninitialized constant TableEngine
UPDATE. Why dup
is needed:
Notice, the class SomeClass
is a shortcut for creating an object of type Class
and assigning it to some constant:
SomeClass = Class.new
When you create a class, its name value isn't set:
klass = Class.new
# => #<Class:0x00000001545a28>
klass.name
# => nil
When you assign it to the constant for the first time, the name is assigned and memoized:
Klass = klass
# => Klass
klass.name
# => "Klass"
When you later assign the object of type Class
to another constant, it remains just the same object, referred by both constants:
NewKlass = Klass
# => Klass
Klass.name
# => "Klass"
NewKlass.name
# => "Klass"
That's why even if the initial constant will be removed, the object will keep carrying the old name.
Object.send :remove_const, :Klass
# => Klass
NewKlass
# => Klass
NewKlass.name
# => "Klass"
Klass
# => NameError: uninitialized constant Klass
The object by itself hasn't been changed. What has been changed is the list of constants, carried by the Object
object.
When you duplicate the object of type Class
it is created without any name (it is the new object):
new_klass = NewKlass.dup
# => #<Class:0x000000016ced90>
new_klass.name
# => nil
And when you assing it to the new constant, the name is set. That is how in the very first example above it receives the new name:
Posts = TableEngine::Posts.dup
# => Post