2017-10-12 1 views
1

Ich möchte wissen, wie jede Konstante auf dem Digest Modul im Voraus programmgesteuert zu sehen. Das Verhalten unten zu sehen ist aufgrund const_missinghere verwendet:Alle Konstanten in "Digest" anzeigen

require 'digest' 

Digest.constants 
#=> [:Class, :REQUIRE_MUTEX, :Instance, :Base] 

Digest::MD5 
Digest.constants 
#=> [:Class, :REQUIRE_MUTEX, :Instance, :Base, :MD5] 

Digest::SHA1 
Digest.constants 
#=> [:Class, :REQUIRE_MUTEX, :Instance, :Base, :MD5, :SHA1] 

Da sie in möglichst verdaut werden Metaprogrammierung, wie kann ich wissen, alle möglichen verfügbaren verdaut?

Für Wissen, diejenigen, die 2.4.1 in Ruby verfügbar zu sein scheinen sollte [:SHA256, :SHA384, :SHA512, :SHA1, :SHA2, :MD5, :RMD160]

+0

Ein Weg ist es, in den Quellcode zu schauen: https://github.com/ruby/ruby/tree/trunk/ext/digest –

+0

Außer dieser Kommentar scheint sonst zu sagen: https://github.com/ ruby/ruby ​​/ blob/trunk/ext/verdauen/lib/digest.rb # L103 Und Sie können SHA512 laden, die nicht in der Quelle ist. – BookOfGreg

+1

Guter Punkt. Nun, da Konstanten lazy geladen sind, sehe ich nicht, wie Sie sie auflisten können, ohne sie bereits zu kennen. ¯ \\ _ (ツ) _/¯ –

Antwort

0

Hier ist ein Code aus dem aktuellen master branch of ruby snipped:

module Digest 
    def self.const_missing(name) # :nodoc: 
    case name 
    when :SHA256, :SHA384, :SHA512 
     lib = 'digest/sha2.so' 
    else 
     lib = File.join('digest', name.to_s.downcase) 
    end 

    begin 
     require lib 
    rescue LoadError 
     raise LoadError, "library not found for class Digest::#{name} -- #{lib}", caller(1) 
    end 
    unless Digest.const_defined?(name) 
     raise NameError, "uninitialized constant Digest::#{name}", caller(1) 
    end 
    Digest.const_get(name) 
    end 

    # ... 
end 

... So können Sie‘ t liste wirklich alle Konstanten auf, ohne sie bereits zu kennen! Sie müssen entweder require die notwendige Datei, oder referenzieren Sie die Konstante direkt (die Datei wird dynamisch geladen, wie oben gesehen).

Jede Umgehungslösung, die ich geben könnte, würde nur für eine bestimmte Version von Ruby funktionieren. Sie wären besser dran, nur read the documentation und laden Sie jede Bibliothek explizit, leider!