1

我正在使用一个不处理命名空间模型的库。我有一个 Rails 引擎,其中包含我需要使用的所有 ActiveRecord 模型,因此我使用引擎的命名空间引用它们,例如:TableEngine::Posts。

Ruby 中有没有办法取消 Posts 类的命名空间?

就像是

TableEngine::Posts.demodulize # => Posts
4

2 回答 2

2

首先,您可以添加所需的常量并将 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
于 2015-06-18T20:48:08.307 回答
0

我最终使用了@Andrew 建议的解决方案,稍作改动:

::Posts = TableEngine::Posts.dup

添加 '::' 可以防止 Posts 类被创建它的上下文命名空间,例如:

class PostsController < ApplicationController
    Posts = TableEngine::Posts.dup # => PostsController::Posts
    ::Posts = TableEngine::Posts.dup # => Posts
end
于 2015-06-19T18:06:45.683 回答