Ruby 如何命名嵌套 class 的父 class

How does Ruby namespace the parent class of a nested class

在与 Ruby gem 权威人士合作时,我意识到我不确定某些命名空间在 Ruby 中的工作方式,而且我不喜欢 mysteries/uncertainties介意。

Pundit 建议您这样设置 application_policy.rb

class ApplicationPolicy
  class Scope
     .
     .
     .
  end
end

class 内部实际发生的事情并不重要,重要的是 class 的结构。

然后您为继承自 ApplicationPolicy 的特定资源指定策略,这样说 post_policy.rb

class PostPolicy < ApplicationPolicy
  class Scope < Scope
  end
end

我的一般问题是,在我的 PostPolicy 中,当我声明 Scope < Scope 时,父 Scope 指的是什么?它会自动在外部 class 的父级中获得命名空间吗?那么它和从ApplicationPolicy::Scope继承本质上是一样的吗?我自己找不到方法来回答这个问题,谢谢!

自己很容易上手:

class C1; class Nested; end; end
class C2<C1; class Nested<Nested; end; end

C2::Nested.ancestors
#⇒ [
#  [0] C2::Nested < C1::Nested,
#  [1] C1::Nested < Object,
#  [2] Object < BasicObject,
#  [3] PP::ObjectMixin,
#  [4] Kernel,
#  [5] BasicObject
# ]

所以,是的,它被隐式解析为 ApplicationPolicy::Scope

简答

你在这两方面都是对的。您可以使用 Class#ancestors :

检查
class ApplicationPolicy
  class Scope
  end
end

class PostPolicy < ApplicationPolicy
  class Scope < Scope
  end
end

p PostPolicy::Scope.ancestors
#=> [PostPolicy::Scope, ApplicationPolicy::Scope, Object, Kernel, BasicObject]

等效代码

以上代码与:

完全相同
class ApplicationPolicy
end

class ApplicationPolicy::Scope
end

class PostPolicy < ApplicationPolicy
end

class PostPolicy::Scope < ApplicationPolicy::Scope
end

p PostPolicy::Scope.ancestors
#=> [PostPolicy::Scope, ApplicationPolicy::Scope, Object, Kernel, BasicObject]

请注意 PostPolicy::Scope 不继承自 PostPolicy。它们是独立的类,前者恰好定义在后者的命名空间中。

另一种检查方式

class A
  class Scope
  end
end

class B < A
  class Scope < Scope
  end
end

class C
  class Scope < Scope
  end
end

失败:

namespace.rb:26:in `<class:C>': uninitialized constant C::Scope (NameError)
    from namespace.rb:25:in `<main>'

表示Scope必须来自A命名空间。