1

Ruby 1.9を使用するようにPuppetをアップグレードしようとしていますが、定数で問題が発生しています。const_defined?( "Timeout")は、:Timeoutが定数のリストにない場合でも、trueを返します。これはRuby1.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
4

2 に答える 2

2

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 なのに?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 には 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 に Timeout と呼ばれるクラスがあり、時にはチェックする必要がある他のクラスに Timeout と呼ばれる定数があることですが、この変更によりコードは実行にはるかに近づきますルビー1.9。

于 2011-03-25T05:07:47.697 に答える
1

何が起こっているのかはっきりとは言えません。

ただし、 と の RDocは 1.8.7 では異なりますが、1.9 ではかなり似ていますconst_defined?constants

1.8.7では、次のようにconst_defined?述べています。

指定された名前の定数が mod によって定義されている場合、true を返します。

constants言う

mod でアクセス可能な定数の名前の配列を返します。これには、含まれているすべてのモジュールの定数の名前が含まれます (セクションの最初の例)。

ただし、1.9ではconst_defined?

指定された名前の定数が mod によって定義されている場合は true を返し、inherit が false でない場合はその祖先を返します。[デフォルトでinheritは true ]

constants言う

mod でアクセス可能な定数の名前の配列を返します。これには、すべてのパラメーターが false に設定されていない限り、含まれているすべてのモジュール (セクションの最初の例) の定数の名前が含まれます。[デフォルトでallは true ]

したがって、2 つのメソッドの動作は 1.9 では一貫しているように見えますが、1.8.7 では一貫していないようです。しかし、私は間違っている可能性があります。

ということで、次のことを提案します。

  • と を使用するおもちゃの例を作成しconst_defined?constantsできれば を使用せずにTimeout、1.8 と 1.9 の両方で 2 つのメソッドが何をするかを理解できると確信できるまで、それを試してみてください。
  • 定数がどこにTimeout属しているかを調べます。また、以前は定義されていなかった Timeout が IRB またはデバッガーによって定義される可能性があるかどうか、および Ruby の 1 つのバージョンではデフォルトでロードされ、他のバージョンではロードされないかどうかを確認します。

. _ _ const_defined? 1.8 1.9_ 関連性があるかどうかはわかりません。

これがお役に立てば幸いです-よくわかりませんが!

于 2011-03-23T01:25:16.873 に答える