我正在使用一个不处理命名空间模型的库。我有一个 Rails 引擎,其中包含我需要使用的所有 ActiveRecord 模型,因此我使用引擎的命名空间引用它们,例如:TableEngine::Posts。
Ruby 中有没有办法取消 Posts 类的命名空间?
就像是
TableEngine::Posts.demodulize # => Posts
我正在使用一个不处理命名空间模型的库。我有一个 Rails 引擎,其中包含我需要使用的所有 ActiveRecord 模型,因此我使用引擎的命名空间引用它们,例如:TableEngine::Posts。
Ruby 中有没有办法取消 Posts 类的命名空间?
就像是
TableEngine::Posts.demodulize # => Posts
首先,您可以添加所需的常量并将 Class/Module 分配给它(记住两者都只是对象)。您应该复制它以重置名称:
Posts = TableEngine::Posts.dup
然后删除源常量名称:
Object.send :remove_const, :TableEngine
然后:
Posts
# => Posts
TableEngine
# => NameError: uninitialized constant TableEngine
TableEngine::Posts
# => NameError: uninitialized constant TableEngine
更新。为什么dup
需要:
请注意,这class SomeClass
是创建类型对象Class
并将其分配给某个常量的快捷方式:
SomeClass = Class.new
创建类时,它的名称值未设置:
klass = Class.new
# => #<Class:0x00000001545a28>
klass.name
# => nil
当您第一次将其分配给常量时,会分配并记住名称:
Klass = klass
# => Klass
klass.name
# => "Klass"
当您稍后将类型对象分配Class
给另一个常量时,它仍然是同一个对象,由两个常量引用:
NewKlass = Klass
# => Klass
Klass.name
# => "Klass"
NewKlass.name
# => "Klass"
这就是为什么即使删除了初始常量,该对象仍将保留旧名称。
Object.send :remove_const, :Klass
# => Klass
NewKlass
# => Klass
NewKlass.name
# => "Klass"
Klass
# => NameError: uninitialized constant Klass
对象本身没有改变。Object
改变的是对象携带的常量列表。
当您复制类型的对象时,Class
它创建时没有任何名称(它是新对象):
new_klass = NewKlass.dup
# => #<Class:0x000000016ced90>
new_klass.name
# => nil
当您将其分配给新常量时,名称已设置。这就是在上面的第一个示例中它接收新名称的方式:
Posts = TableEngine::Posts.dup
# => Post
我最终使用了@Andrew 建议的解决方案,稍作改动:
::Posts = TableEngine::Posts.dup
添加 '::' 可以防止 Posts 类被创建它的上下文命名空间,例如:
class PostsController < ApplicationController
Posts = TableEngine::Posts.dup # => PostsController::Posts
::Posts = TableEngine::Posts.dup # => Posts
end