Ruby 1.9 const_defined?(「タイムアウト」)は、タイムアウトが定数のリストにない場合にtrueを返します

StackOverflow https://stackoverflow.com/questions/5395587

  •  28-10-2019
  •  | 
  •  

質問

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. 。関連性があるかどうかはわかりません。

私はこれが役立つことを願っています - 私は確かではありません!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top