ruby convierte el nombre de la clase en una cadena a la clase real

87

¿Cómo llamo a una clase desde una cadena que contiene ese nombre de clase dentro de ella? (Supongo que podría hacer caso / cuándo, pero eso parece feo).

La razón por la que pregunto es porque estoy usando el acts_as_commentablecomplemento, entre otros, y estos almacenan commentable_type como una columna. Quiero poder llamar a cualquier clase comentable en particular para hacer un comentario find(commentable_id).

Gracias.

sin clasificar
fuente

Respuestas:

131

Creo que lo que quieres es constantize

Esa es una construcción RoR. No se si hay uno para ruby ​​core

Jamie Wong
fuente
perfecto, eso es justo lo que estaba buscando.
sin clasificar
40
Para Ruby simple, usarías Module.const_get. La ventaja de constantizees que funciona incluso con espacios de nombres profundamente anidados, por lo que podría hacer 'Functional::Collections::LazyList'.constantizey obtener la clase LazyList del módulo Colecciones en el módulo Funcional, mientras que con const_get, tendría que hacer algo como 'Functional::Collections::LazyList'.split('::').reduce(Module, :const_get).
Chuck
45
"Object".constantize # => Object
jtbandes
fuente
Tenga en cuenta que .constantizees un método Rails, no lo encontrará en Ruby simple
Edgar Ortega
34

Dada una cadena, primero llame a classify para crear un nombre de clase (sigue siendo una cadena), luego llame a constantize para intentar encontrar y devolver la constante de nombre de clase (tenga en cuenta que los nombres de clase son constantes ).

some_string.classify.constantize
usuario664833
fuente
10
Debe usar camelize en lugar de classify, ya que classify es para nombres de tablas y no maneja muy bien la pluralización.
Peter Brown
1
¡Gracias! ¡eso es genial!
duykhoa
2
Su respuesta es realmente valiosa, pero debe usar "titleize" para el nombre de la tabla que incluye el espacio, y eliminar el espacio en blanco de la cadena para que signifique el nombre completo de la clase.
SSR
22

Sé que esta es una pregunta antigua, pero solo quiero dejar esta nota, puede ser útil para otros.

En Ruby simple, Module.const_getpuede encontrar constantes anidadas. Por ejemplo, tener la siguiente estructura:

module MyModule
  module MySubmodule
    class MyModel
    end
  end
end

Puede usarlo de la siguiente manera:

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

Cuando ActiveSupport está disponible (por ejemplo, en Rails): String#constantizeo String#safe_constantize, eso es "ClassName".constantize.

En Ruby puro:, Module#const_gettípicamente Object.const_get("ClassName").

En rubíes recientes, ambos funcionan con constantes anidadas en módulos, como en Object.const_get("Outer::Inner").

skalee
fuente
6

Si desea convertir la cadena al nombre de la clase actual para acceder al modelo o cualquier otra clase

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
fuente