ruby converte o nome da classe em string para a classe real

86

Como faço para chamar uma classe de uma string contendo o nome da classe dentro dela? (Eu acho que poderia fazer caso / quando, mas isso parece feio.)

A razão de eu perguntar é porque estou usando o acts_as_commentableplugin, entre outros, e eles armazenam o commentable_type como uma coluna. Eu quero ser capaz de chamar qualquer classe comentável em particular para fazer umfind(commentable_id) sobre ela.

Obrigado.

não triados
fonte

Respostas:

129

Acho que o que você quer é constantize

Essa é uma construção RoR. Não sei se tem um para núcleo de rubi

Jamie Wong
fonte
perfeito, era exatamente isso que eu procurava.
não classificado de
40
Para Ruby simples, você usaria Module.const_get. A vantagem do constantizeé que funciona mesmo com namespaces profundamente aninhados, então você pode fazer 'Functional::Collections::LazyList'.constantizee obter a classe LazyList do módulo Coleções no módulo Funcional, enquanto com const_get, você teria que fazer algo parecido 'Functional::Collections::LazyList'.split('::').reduce(Module, :const_get).
Chuck
44
"Object".constantize # => Object
jtbandes
fonte
Observe que .constantize é um método Rails, você não o encontrará em Ruby simples
Edgar Ortega
33

Dada uma string, primeira chamada classify para criar um nome de classe (ainda uma string) e, em seguida, chame constantize para tentar encontrar e retornar a constante do nome da classe (observe que os nomes das classes são constantes ).

some_string.classify.constantize
user664833
fonte
10
Você deve usar camelize em vez de classify, pois classify é para nomes de tabelas e não lida muito bem com a pluralização.
Peter Brown
1
Obrigado! isso é ótimo!
duykhoa
2
Sua resposta é realmente valiosa, mas você deve usar "titleize" para o nome da tabela, que inclui espaço, e remover o espaço em branco da string para tornar o nome completo da classe um significado.
SSR
22

Eu sei que esta é uma pergunta antiga, mas eu só quero deixar esta nota, pode ser útil para outras pessoas.

Em Ruby simples, Module.const_getpode encontrar constantes aninhadas. Por exemplo, tendo a seguinte estrutura:

module MyModule
  module MySubmodule
    class MyModel
    end
  end
end

Você pode usá-lo da seguinte maneira:

Module.const_get("MyModule::MySubmodule::MyModel")
MyModule.const_get("MySubmodule")
MyModule::MySubmodule.const_get("MyModel")
Edgar Ortega
fonte
7

Quando ActiveSupport está disponível (por exemplo, em Rails): String#constantizeou String#safe_constantize, isto é "ClassName".constantize.

Em Ruby puro:, Module#const_getnormalmente Object.const_get("ClassName").

Em rubis recentes, ambos trabalham com constantes aninhadas em módulos, como em Object.const_get("Outer::Inner").

Skalee
fonte
6

Se você deseja converter string em nome de classe atual para acessar o modelo ou qualquer outra classe

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`
SSR
fonte