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.

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


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

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

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")

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").


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`
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.