gpt4 book ai didi

Ruby 1.9 const_defined? ("Timeout") 当 Timeout 不在常量列表中时返回 true

转载 作者:太空宇宙 更新时间:2023-11-03 18:30:06 30 4
gpt4 key购买 nike

我正在尝试升级 Puppet 以使用 Ruby 1.9,但遇到了常量问题。 const_defined?("Timeout") 返回真,即使 :Timeout 不在常量列表中。这不会发生在 Ruby 1.8.7 上。有什么想法吗?

[128, 137] in /Users/matthewrobinson/work/puppet/lib/puppet/util/classgen.rb
128 def handleclassconst(klass, name, options)
129 const = genconst_string(name, options)
130
131 require 'ruby-debug';
132 debugger if const == "Timeout"=>
133 if const_defined?(const)
134 if options[:overwrite]
135 Puppet.info "Redefining #{name} in #{self}"
136 remove_const(const)
137 else
(rdb:1) const
=> "Timeout"
(rdb:1) const_defined?(const)
=> true
(rdb:1) constants.grep /Timeout/
=> []
(rdb:1) constants
=> [:Ensure, :ParameterName, :Auth_type, :Allow_root, :Authenticate_user, :Auth_class, :Comment, :Group, :K_of_n, :Mechanisms, :Rule, :Session_owner, :Shared, :MetaParamNoop, :MetaParamSchedule, :MetaParamAudit, :MetaParamCheck, :MetaParamLoglevel, :MetaParamAlias, :MetaParamTag, :RelationshipMetaparam, :MetaParamRequire, :MetaParamSubscribe, :MetaParamBefore, :MetaParamNotify, :MetaParamStage, :Component, :Macauthorization, :Expirer, :ClassMethods, :InstanceMethods, :ExecutionStub, :POSIX, :Errors, :MethodHelper, :ClassGen, :Docs, :Execution, :Tagging, :Log, :Logging, :Package, :Warnings, :Cacher, :Autoload, :LoadedFile, :Settings, :Feature, :SUIDManager, :RunMode, :CommandLine, :InstanceLoader, :Pson, :Metric, :LogPaths, :ProviderFeatures, :InlineDocs, :FileLocking, :Storage, :Checksums]
(rdb:1) constants.grep /Path/
=> [:LogPaths]
(rdb:1) self
=> Puppet::Type::Macauthorization

最佳答案

const_defined 的行为?通过将新的 inherit 参数设置为 false,可以使 Ruby 1.9 中的版本与 Ruby 1.8 中的版本相同。

mod.const_defined?(sym, inherit=true)

这里有一个例子来说明不同的行为。

module Foo
def self.bar
puts "The constant I got was #{const_get("Timeout")}"
if const_defined?("Timeout")
puts "I found #{Timeout}!"
remove_const("Timeout")
puts "Timeout is now #{Timeout}"
end
end
end

class Timeout
end

puts Foo.bar

在 Ruby 1.9.2 下运行的输出是:

The constant I got was Timeout
I found Timeout!
19_test.rb:6:in `remove_const': constant Foo::Timeout not defined (NameError)
from 19_test.rb:6:in `bar'
from 19_test.rb:13:in `<main>'

所以即使const_defined?认识到 Timeout 在顶级范围内被定义为一个类,remove_const 只允许删除 Foo 范围内的常量。

在 Ruby 1.8.7 中,输出是:

The constant I got was Timeout
nil

所以 const_get 就像在 Ruby 1.9.2 中一样查看祖先作用域,但是 const_defined?不会,这会阻止 remove_const 被调用。

Ruby 1.9.2 可以像 1.8.7 一样运行:

module Foo
def self.bar
puts "The constant I got was #{const_get("Timeout")}"
if const_defined?("Timeout", false)
puts "I found #{Timeout}!"
remove_const("Timeout")
puts "Timeout is now #{Timeout}"
end
end
end

class Timeout
end

puts Foo.bar

但是,自 const_defined 以来,这现在不向后兼容 Ruby 1.8 了吗? 1.8 中没有第二个参数。为了解决这个问题,我制作了以下可以调用的方法而不是 const_defined?并用于任一版本的 Ruby。

def is_constant_defined?(const)
if ::RUBY_VERSION =~ /1.9/
const_defined?(const, false)
else
const_defined?(const)
end
end

这解决了这个特定的 Ruby 1.9 升级问题。它可能不是最好的长期解决方案,真正的问题是在 topscope 有一个名为 Timeout 的类,有时在其他类中有一个名为 Timeout 的常量需要检查,但这种变化使代码更接近运行 ruby 1.9。

关于Ruby 1.9 const_defined? ("Timeout") 当 Timeout 不在常量列表中时返回 true,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5395587/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com