Ruby 1.9 const_defined?(「タイムアウト」)は、タイムアウトが定数のリストにない場合にtrueを返します
質問
Ruby 1.9を使用するために人形をアップグレードし、定数でトラブルに出くわしようとしています。 const_defined?( "Timeout")は、Timeoutが定数のリストに含まれていない場合でもtrueを返しています。これは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の動作? Ruby 1.9では、新しい継承パラメーターをFalseに設定することにより、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であっても?タイムアウトがトップスコープでクラスとして定義されていることを認識してください。Remove_Constは、Fooのスコープで定数を削除することのみを許可されています。
Ruby 1.8.7では、出力は次のとおりです。
The constant I got was Timeout
nil
それで、const_getはRuby 1.9.2のように祖先のスコープを見ますが、const_defined? remode_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に2番目のパラメーターはありません。これを回避するために、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でタイムアウトと呼ばれるクラスがあり、時にはチェックする必要がある他のクラスではタイムアウトと呼ばれる定数があることですが、この変更により、コードが実行されるのがはるかに近くなります。ルビー1.9。
他のヒント
何が起こっているのか確かに言うことはできません。
ただし、RDOCの const_defined?
と constants
1.8.7では異なりますが、1.9ではかなり似ています。
の 1.8.7, const_defined?
言う:
指定された名前の定数がmodによって定義されている場合、trueを返します。
と constants
言う
modでアクセス可能な定数の名前の配列を返します。 これには、含まれるモジュールの定数の名前が含まれます(セクションの開始時の例)。
しかし、で 1.9, const_defined?
言う
指定された名前の定数がmodによって定義されている場合、または継承が偽でない場合はその祖先がtrueを返します。 [デフォルトでは、
inherit
本当です
と constants
言う
modでアクセス可能な定数の名前の配列を返します。これには、すべてのパラメーターがfalsに設定されていない限り、含まれるモジュールの定数の名前(セクションの開始の例)が含まれます。 [デフォルトでは、
all
本当です
したがって、2つの方法の動作は1.9で一貫しているように見えますが、1.8.7では一貫していないようです。しかし、私は間違っている可能性があります。
そうは言っても、私は次のことを提案します:
- 使用のおもちゃの例を作成します
const_defined?
とconstants
, 、できれば関与しないTimeout
, 、そして、1.8と1.9の両方で、2つの方法が何をするかを理解すると確信するまで、それを振り返ります。 - どこでうまくいってください
Timeout
定数はに属します。また、IRBまたはデバッガーが以前に定義されていたときにタイムアウトが定義される可能性があるかどうか、および1つのバージョンのRubyによってデフォルトでロードされるかどうかを確認しますが、他のバージョンではありません。
私も出会いました http://redmine.ruby-lang.org/issues/1915 グーグルでグーグルするとき const_defined? 1.8 1.9
. 。関連性があるかどうかはわかりません。
私はこれが役立つことを願っています - 私は確かではありません!