2016-06-14 14 views
5

Mam moduł, który zawiera klasę o nazwie String (między innymi). Muszę wyszukać klasę według nazwy i z wdziękiem powrócić, jeśli nie ma takiej klasy.Czy można zawęzić ciągłe wyszukiwanie ruby?

module Mod1 
    module String 
    end 
end 
Mod1.const_get 'String' 
#⇒ Mod1::String 
Kernel.const_get '::Mod1::String' 
#⇒ Mod1::String 

jak dotąd, bardzo dobrze. Oczekuję otrzymania NameError, gdy próbuję wyszukać nieistniejącą klasę, co jest w porządku. Problem polega na tym, że jeśli istnieje klasa o podanej nazwie istniejącego w globalnej przestrzeni nazw, jest ona zwracana:

Mod1.const_get 'Fixnum' 
#⇒ Fixnum < Integer 
Kernel.const_get '::Mod1::Fixnum' 
#⇒ Fixnum < Integer 

Rozumiem powody, ale moje pytanie byłoby: jest tam out-of -the-box metoda wyszukiwania stałej tylko w podanej przestrzeni nazw?

Teraz mogę sprawdzić wynik z

result.to_s.start_with?(namespace) 

ale to na pewno nie jest to najbardziej wyrafinowane sposób zawęzić odnośnika.

Odpowiedz

7

Odpowiedź brzmi:

Mod1.const_get 'Fixnum', false 

Oto doc:

/* 
* call-seq: 
*  mod.const_get(sym, inherit=true) -> obj 
*  mod.const_get(str, inherit=true) -> obj 
* 
* Checks for a constant with the given name in <i>mod</i>. 
* If +inherit+ is set, the lookup will also search 
* the ancestors (and +Object+ if <i>mod</i> is a +Module+). 
* 
* The value of the constant is returned if a definition is found, 
* otherwise a +NameError+ is raised. 
* 
*  Math.const_get(:PI) #=> 3.14159265358979 
* 
* This method will recursively look up constant names if a namespaced 
* class name is provided. For example: 
* 
*  module Foo; class Bar; end end 
*  Object.const_get 'Foo::Bar' 
* 
* The +inherit+ flag is respected on each lookup. For example: 
* 
*  module Foo 
*  class Bar 
*   VAL = 10 
*  end 
* 
*  class Baz < Bar; end 
*  end 
* 
*  Object.const_get 'Foo::Baz::VAL'   # => 10 
*  Object.const_get 'Foo::Baz::VAL', false # => NameError 
* 
* If the argument is not a valid constant name a +NameError+ will be 
* raised with a warning "wrong constant name". 
* 
* Object.const_get 'foobar' #=> NameError: wrong constant name foobar 
* 
*/ 

https://github.com/ruby/ruby/blob/449fbfd4d4ce47be227804c22214fed32a5b0124/object.c#L2027

+1

Perfect, dzięki. Ewidentna porada "spójrz na dokumentację metody" działa tak jak zwykle. – mudasobwa

+0

Czy mogę zaproponować linkowanie do dokumentów zamiast źródła MRI? http://ruby-doc.org/core-2.3.1/Module.html#method-i-const_get –