ruby konwertuje nazwę klasy w łańcuchu na aktualną klasę


87

Jak wywołać klasę z łańcucha zawierającego nazwę klasy w środku? (Myślę, że mógłbym zrobić przypadek / kiedy, ale to wydaje się brzydkie.)

Pytam, ponieważ używam acts_as_commentablemiędzy innymi wtyczki i przechowują one parametr commentable_type jako kolumnę. Chcę móc przywołać jakąkolwiek klasę, którą można komentować, aby to zrobiła find(commentable_id).

Dzięki.

Odpowiedzi:


131

Myślę, że chcesz constantize

To jest konstrukcja RoR. Nie wiem, czy jest jeden na rdzeń rubinowy


idealnie, właśnie tego szukałem.
nieposortowane

40
W przypadku zwykłego Rubiego użyłbyś Module.const_get. Zaletą constantizejest to, że działa nawet z głęboko zagnieżdżonymi przestrzeniami nazw, więc możesz zrobić 'Functional::Collections::LazyList'.constantizei pobrać klasę LazyList z modułu Kolekcje w module Functional, podczas gdy z const_get, musisz zrobić coś podobnego 'Functional::Collections::LazyList'.split('::').reduce(Module, :const_get).
Chuck

45
"Object".constantize # => Object

Zwróć uwagę, że .constantizejest to metoda Railsów, nie znajdziesz jej w zwykłym Ruby
Edgar Ortega

35

Biorąc pod uwagę łańcuch, najpierw wywołaj classify, aby utworzyć nazwę klasy (nadal ciąg), a następnie wywołaj constantize, aby spróbować znaleźć i zwrócić stałą nazwy klasy (zwróć uwagę, że nazwy klas są stałymi ).

some_string.classify.constantize

10
Powinieneś używać camelize zamiast classify, ponieważ klasyfikacja jest przeznaczona dla nazw tabel i nie obsługuje zbyt dobrze liczby mnogiej.
Peter Brown,

1
Dzięki! to wspaniale!
duykhoa

2
Twoja odpowiedź jest naprawdę cenna, ale powinieneś użyć "titleize" dla nazwy tabeli zawierającej spacje i usunąć spacje z ciągu, aby nadać znaczenie pełnej nazwie klasy.
SSR

22

Wiem, że to stare pytanie, ale chcę tylko zostawić tę notatkę, może być pomocna dla innych.

W zwykłym Rubim Module.const_getmożna znaleźć zagnieżdżone stałe. Na przykład o następującej strukturze:

module MyModule
  module MySubmodule
    class MyModel
    end
  end
end

Możesz go użyć w następujący sposób:

Module.const_get("MyModule::MySubmodule::MyModel")
MyModule.const_get("MySubmodule")
MyModule::MySubmodule.const_get("MyModel")


6

Jeśli chcesz przekonwertować ciąg na rzeczywistą nazwę klasy, aby uzyskać dostęp do modelu lub dowolnej innej klasy

str = "group class"

> str.camelize.constantize 'or'
> str.classify.constantize 'or'
> str.titleize.constantize

Example :
  def call_me(str)
    str.titleize.gsub(" ","").constantize.all
  end

Call method : call_me("group class")

Result:
  GroupClass Load (0.7ms) SELECT `group_classes`.* FROM `group_classes`
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.