【问题标题】:How does Ruby namespace the parent class of a nested classRuby如何命名嵌套类的父类
【发布时间】:2016-12-21 17:41:52
【问题描述】:

在使用 Ruby gem Pundit 时,我意识到我不确定 Ruby 中某些命名空间的工作方式,并且我不喜欢我心中的奥秘/不确定性。

Pundit 建议您像这样设置application_policy.rb

class ApplicationPolicy
  class Scope
     .
     .
     .
  end
end

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

然后,您为从 ApplicationPolicy 继承的特定资源指定策略,例如 post_policy.rb

class PostPolicy < ApplicationPolicy
  class Scope < Scope
  end
end

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

【问题讨论】:

    标签: ruby namespaces ruby-2.0 pundit


    【解决方案1】:

    简答

    你在这两个方面都是对的。您可以通过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命名空间。

    【讨论】:

    • 感谢您的快速回复,很抱歉花了一些时间回复。你的回答太棒了,超级彻底!谢谢你。出于某种原因,class Scope &lt; Scope 的简写实际上指的是ApplicationPolicy::Scope 对我来说似乎并不自然或我所期望的,但我想它就是这样,至少现在我明白了!
    • 下面的场景很有趣且有点令人困惑:[1] pry(main)> class C1 [1] pry(main)* end => nil [2] pry(main)> class C2 ' [3] 撬(主)>
    • 不定义C1::Nested,错误信息为NameError: uninitialized constant C2::Nested
    • 不客气。我同意语法有点太复杂了。我不会将它用于其他人应该阅读的任何内容。
    【解决方案2】:

    很容易搞定自己:

    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

    【讨论】:

    • 感谢您展示您如何确定它,谢谢!
    • 下面的场景很有趣且有点令人困惑:[1] pry(main)> class C1 [1] pry(main)* end => nil [2] pry(main)> class C2 ' [3] 撬(主)>
    • 所以,通过不定义 C1::Nested,错误信息是 NameError: uninitialized constant C2::Nested,这对你有意义吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-24
    • 2019-08-24
    • 2017-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多