【问题标题】:Create multilevel constant in ruby在 ruby​​ 中创建多级常量
【发布时间】:2013-05-24 20:29:34
【问题描述】:

鉴于我有一个常量名称 Foo::Bar::Baz,我如何深入了解每个级别并确定该常量是否存在?

【问题讨论】:

  • 你的问题是Foo::BarFoo是否存在? AFAIK,除非 Foo::Bar 已经存在,否则 Ruby 不会创建 Foo::Bar::Baz

标签: ruby-on-rails ruby


【解决方案1】:
defined?(Foo) # => nil

module Foo; end
defined?(Foo) # => "constant"
defined?(Foo::Bar) # => nil

module Foo::Bar; end
defined?(Foo::Bar) # => "constant"
defined?(Foo::Bar::Baz) # => nil

module Foo::Bar; Baz = :baz end
defined?(Foo::Bar::Baz) # => "constant"

【讨论】:

    【解决方案2】:

    其他人谈论defined? 运算符(是的,它是内置的一元运算符,而不是方法!!!),但还有其他方法。我个人比较喜欢这个:

    constants #=> a big array of constant names
    constants.include? :Foo #=> false
    module Foo; end
    constants.include? :Foo #=> true
    Foo.constants.include? :Bar #=> false
    module Foo
      module Bar; end
    end
    Foo.constants.include? :Bar #=> true
    # etc.
    

    关于defined? 运算符,我必须承认的一件事是它的可靠性。它不是一种方法,因此永远无法重新定义,因此总是按照您的期望行事。另一方面,可以使用更多迂回(且不太可靠)的方式,例如:

    begin
      Foo::Bar::Baz
      puts "Foo::Bar::Baz exists!"
    rescue NameError
      puts "Foo::Bar::Baz does not exist!"
    end
    

    【讨论】:

      【解决方案3】:

      如果其他人遇到这种情况,我最终会这样做:

      unless Object.const_defined? const_name
        const_name.split('::').inject(Object) do |obj, const|
          unless obj.const_defined? const
            # create the missing object here...
          end
          obj.const_get(const)
        end
      end
      

      【讨论】:

      • 为什么不只是#const_defined?
      • 我已经更新了我的答案以使用它,这消除了对 ActiveSupport 的需要。谢谢!
      【解决方案4】:

      听起来你想使用定义的?操作员。 Check if a constant is already defined 对此有更多了解。

      【讨论】:

      • 如果它像一种方法一样嘎嘎作响... ;)
      • 在某种程度上,是的。但它不能(感谢天堂!)重新定义。有时我希望#! 也不是一种方法。无论如何,+1,正确答案。
      猜你喜欢
      • 2011-02-21
      • 1970-01-01
      • 2011-08-07
      • 2013-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多