【问题标题】:Ruby: Is there a way to get the enclosing Module const of a Class?Ruby:有没有办法获得一个类的封闭模块常量?
【发布时间】:2011-09-06 16:07:03
【问题描述】:

我正在用 Ruby 进行一些元编程,我需要在模块内动态生成同级类。这样做时,我想在模块上调用 const_set,但直到运行时我才知道要调用哪个模块常量。一个例子:

给定的类

Foo::Bar::Baz
Foo::Quox::Quack

我希望能够调用这样的函数(此处过于简化):

def generate_from klass
  mod = klass.enclosing_module # <- THIS LINE is the one I need to figure out
  mod.const_set("GeneratedClassName", Class.new)
end

当我使用Baz 调用时,我想得到一个新类,定义为

Foo::Bar::GeneratedClassName

还有一个嘎嘎,我想要

Foo::Quox::GeneratedClassName

我知道的唯一方法是拆分 klass.name,然后在这些字符串上反复调用 const_get,并进行常量化。有谁知道更优雅的方式?

【问题讨论】:

  • 我知道的唯一两种方法是您在底部描述的方式,并且在每个类中都包含一个 get_module 函数。但是,感觉应该有办法做到这一点。关注这个...

标签: ruby metaprogramming


【解决方案1】:

这应该会让你走上正轨:

module Foo
  module Bar
    class Baz
      def initialize
        @nesting = Module.nesting
      end

      def enclosing_module
        @nesting.last
      end
    end
  end
end

puts Foo::Bar::Baz.new.enclosing_module #=> Foo

相关文档:

http://ruby-doc.org/core/classes/Module.html#M000441

【讨论】:

  • 这对继承不起作用(或可能会做一些意想不到的事情)——如果你创建一个子类Corge::Qux &lt; Foo::Bar::BazCorge::Qux.new.enclosing_module 仍然是Foo
  • 是的。我承认没有用继承进行测试,这就是为什么我说“应该让你走上正轨”,而不是“正是你需要的”。不过感谢您的反馈!
【解决方案2】:

知道了。 ActiveSupport 有这个 Ruby 扩展,Module#parent。对我来说已经足够了。

【讨论】:

  • 我发现了另一种方法可以帮助您,以防您不想仅为此使用 ActiveSupport。不过,如果您仍然使用 Rails,那就不用担心了。
  • 我接受了我的回答,因为它完全符合我的要求并且我正在使用 ActiveSupport,但我赞成 Michael 的回答,因为它在不使用 ActiveSupport 时似乎也是正确的
【解决方案3】:

在 Rails 中,您可以使用 deconstantizeconstantize 的组合。

'Foo::Bar::Baz'.deconstantize.constantize # => Foo::Bar

所以在类的方法中可以这样使用:

self.class.name.deconstantize.constantize

【讨论】:

    【解决方案4】:

    如果有人正在寻找纯 ruby​​ 版本:

      def get_parent_type
        #Note: This will break for base types (lacking '::' in the name)
        parent_type=self.class.name.split('::')[0...-1]
        begin
          Object.const_get(parent_type.join('::'))
        rescue NameError => e
          nil
        end
      end
    

    【讨论】:

      猜你喜欢
      • 2014-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-13
      • 2019-07-05
      • 2018-07-11
      • 1970-01-01
      相关资源
      最近更新 更多