Ruby 1.9 const_definido?(“Timeout”) devuelve verdadero cuando el tiempo de espera no está en la lista de constantes

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

  •  28-10-2019
  •  | 
  •  

Pregunta

Estoy intentando actualizar Puppet para usar Ruby 1.9 y tengo problemas con las constantes.const_definido?("Timeout") devuelve verdadero aunque :Timeout no esté en la lista de constantes.Esto no sucede en Ruby 1.8.7.¿Alguna idea de por qué?

[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
¿Fue útil?

Solución

El comportamiento de const_defined? En Ruby 1.9 se puede hacer que sea lo mismo que en Ruby 1.8 estableciendo el nuevo parámetro de herencia en falso.

mod.const_defined?(sym, inherit=true)

Aquí hay un ejemplo para ilustrar el comportamiento diferente.

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

Bajo Ruby 1.9.2 La salida de la ejecución es:

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

Entonces, aunque const_defined? Reconoce que el tiempo de espera se define en el alcance superior como clase, Remove_Const solo se permite eliminar las constantes en el alcance de Foo.

En Ruby 1.8.7 la salida es:

The constant I got was Timeout
nil

Entonces, const_get mira los alcances del antepasado como en Ruby 1.9.2, pero const_defined? no lo hace, lo que evita que se llame remove_const.

Se puede hacer que Ruby 1.9.2 se comporte como 1.8.7 como así:

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

Sin embargo, esto ahora no es compatible con el retroceso con Ruby 1.8 desde const_defined? No tiene un segundo parámetro en 1.8. Para evitar esto, hice el siguiente método que se puede llamar en lugar de const_defined? y usado en cualquier versión de Ruby.

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

Esto resolvió este problema particular de actualización de Ruby 1.9. Puede que no sea la mejor solución a largo plazo, y el verdadero problema es que hay una clase llamada Tiempo de espera en TopScope y, a veces, una constante llamada Tiempo de espera en otras clases que debe verificarse, pero este cambio se acerca mucho más a Ruby 1.9.

Otros consejos

No puedo decir con seguridad qué está pasando.

Sin embargo, el RDoc para const_defined? y constants es diferente en 1.8.7, mientras que es bastante similar en 1.9.

En 1.8.7, const_defined? dice:

Devuelve verdadero si mod define una constante con el nombre de pila.

y constants dice

Devuelve una matriz de los nombres de las constantes accesibles en mod. Esto incluye los nombres de las constantes en cualquier módulo incluido (ejemplo al inicio de la sección).

Sin embargo, en 1.9, const_defined? dice

Devuelve verdadero si mod define una constante con el nombre de pila, o sus ancestros si heredar no es falso.[por defecto, inherit es verdad]

y constants dice

Devuelve una matriz de los nombres de las constantes accesibles en mod.Esto incluye los nombres de las constantes en cualquier módulo incluido (ejemplo al inicio de la sección), a menos que el parámetro all esté establecido en falso.[por defecto, all es verdad]

Entonces parece que el comportamiento de los dos métodos es consistente en 1.9, pero no consistente en 1.8.7.Pero podría estar equivocado.

Dicho esto, sugeriría lo siguiente:

  • Crea un ejemplo de uso de un juguete const_defined? y constants, preferiblemente sin involucrar Timeout, y juegue con él hasta que esté seguro de que comprende lo que hacen los dos métodos, tanto en 1.8 como en 1.9.
  • Calcula dónde está Timeout pertenece a la constante.También verifique si IRB o el depurador pueden hacer que el tiempo de espera se defina cuando anteriormente no estaba definido, y si una versión de Ruby lo carga de forma predeterminada pero no la otra.

yo también me encontré http://redmine.ruby-lang.org/issues/1915 al buscar en Google const_defined? 1.8 1.9.No estoy seguro si es relevante o no.

Espero que esto ayude, ¡aunque no estoy seguro!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top