Ruby 1.9 const_defined? ("Timeout") restituisce vero quando timeout non nell'elenco delle costanti

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

  •  28-10-2019
  •  | 
  •  

Domanda

Sto cercando di aggiornare il burattino per usare Ruby 1.9 e correre nei guai con le costanti. const_defined? ("timeout") sta tornando vero anche se: il timeout non è nell'elenco delle costanti. Questo non accade su Ruby 1.8.7. Qualche idea perché?

[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
È stato utile?

Soluzione

Il comportamento di const_defined? In Ruby 1.9 può essere realizzato per essere lo stesso di Ruby 1.8 impostando il nuovo parametro ereditario su False.

mod.const_defined?(sym, inherit=true)

Ecco un esempio per illustrare il comportamento diverso.

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

Sotto Ruby 1.9.2 L'output dall'esecuzione di questo è:

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>'

Quindi anche se const_defined? Riconosce che il timeout è definito al primo posto come classe, Rimod_Const è consentito rimuovere le costanti nell'ambito di FOO.

In Ruby 1.8.7 l'uscita è:

The constant I got was Timeout
nil

Quindi const_get guarda gli ambiti dell'antenato proprio come in Ruby 1.9.2, ma const_defined? Non lo fa, che impedisce di essere chiamato Rimoy_Const.

Ruby 1.9.2 può essere fatto per comportarsi come 1.8.7 come così:

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

Tuttavia, questo non è ora compatibile con Ruby 1.8 da Const_Defined? non ha un secondo parametro in 1.8. Per aggirare questo ho realizzato il seguente metodo che può essere chiamato al posto di const_defined? e utilizzata in entrambe le versione di Ruby.

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

Ciò ha risolto questo particolare problema di aggiornamento di Ruby 1.9. Potrebbe non essere la migliore soluzione a lungo termine, e il vero problema è che esiste una classe chiamata timeout a topscope e talvolta una costante chiamata timeout in altre classi che devono essere controllate, ma questa modifica avvicina il codice a correre Ruby 1.9.

Altri suggerimenti

Non posso dire con certezza cosa stia succedendo.

Tuttavia, il RDOC per const_defined? e constants è diverso in 1.8.7, mentre è abbastanza simile in 1.9.

In 1.8.7, const_defined? dice:

Restituisce vero se una costante con il nome dato è definita da mod.

e constants dice

Restituisce un array dei nomi delle costanti accessibili in mod. Ciò include i nomi delle costanti in tutti i moduli inclusi (esempio all'inizio della sezione).

Tuttavia, in 1.9, const_defined? dice

Restituisce vero se una costante con il nome dato è definita da mod o i suoi antenati se eredità non è falso. [Per impostazione predefinita, inherit è vero

e constants dice

Restituisce un array dei nomi delle costanti accessibili in mod. Ciò include i nomi delle costanti in qualsiasi moduli inclusi (esempio all'inizio della sezione), a meno che tutto il parametro non sia impostato su False. [Per impostazione predefinita, all è vero

Quindi sembra che il comportamento dei due metodi sia coerente in 1.9, ma non coerente in 1.8.7. Ma potrei sbagliarmi.

Detto questo, suggerirei quanto segue:

  • Crea un esempio giocattolo di utilizzo const_defined? e constants, preferibilmente non coinvolgere Timeout, e gioca con esso finché non sei sicuro di capire cosa fanno i due metodi, sia sotto 1,8 che 1.9.
  • Affronta dove il Timeout costante appartiene a. Controlla anche se IRB o il debugger possono far definire il timeout quando in precedenza non era definito e se viene caricato per impostazione predefinita da una versione di Ruby ma non dall'altra.

Mi sono anche imbattuto in http://redmine.ruby-lang.org/issues/1915 quando si googla per const_defined? 1.8 1.9. Non sono sicuro che sia rilevante o no.

Spero che questo aiuti - non ne sono sicuro però!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top