¿Cómo convierto un nombre de clase Ruby en un símbolo delimitado por guiones bajos?

95

¿Cómo puedo convertir programáticamente el nombre de una clase FooBar, en un símbolo :foo_bar,? por ejemplo, algo como esto, pero que maneja correctamente el caso camel?

FooBar.to_s.downcase.to_sym
Josh Glover
fuente

Respuestas:

141

Rails viene con un método llamado underscoreque le permitirá transformar cadenas CamelCased en cadenas undercore_separated. Entonces, es posible que pueda hacer esto:

FooBar.name.underscore.to_sym

Pero tendrá que instalar ActiveSupport solo para hacer eso, como dice ipsum.

Si no desea instalar ActiveSupport solo para eso, puede parchear underscoreen Stringusted mismo (la función de subrayado se define en ActiveSupport :: Inflector ):

class String
  def underscore
    word = self.dup
    word.gsub!(/::/, '/')
    word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
    word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
    word.tr!("-", "_")
    word.downcase!
    word
  end
end
kikito
fuente
1
Gracias. Temía que esto fuera una extensión de Rails. :) No te preocupes, ya que en realidad estoy usando Rails.
Josh Glover
2
Entonces debería haber etiquetado su pregunta en consecuencia. Aquí, déjame hacerlo por ti ...
kikito
5
No, no ActiveRecord. ActiveSupport.
Rein Henrichs
De hecho, déjame cambiarlo
kikito
2
¿Cómo hacer lo contrario?
user1406062
72

Carriles 4 .model_name

En Rails 4, devuelve un ActiveModel::Nameobjeto que contiene muchos atributos más "semánticos" útiles como:

FooBar.model_name.param_key
#=> "foo_bar"

FooBar.model_name.route_key
#=> "foo_bars"

FooBar.model_name.human
#=> "Foo bar"

Por lo tanto, debe usar uno de esos si coinciden con el significado deseado, que es probablemente el caso. Ventajas:

  • más fácil de entender tu código
  • su aplicación seguirá funcionando incluso en el caso (poco probable) de que Rails decida cambiar una convención de nomenclatura.

Por cierto, humantiene la ventaja de ser consciente de I18N.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fuente
model_nametambién funciona, por ejemplo, objetos. Ej foo_bar.model_name. : . Si desea la lista completa, escriba foo_bar.model_name.inspecten la consola de rieles o en su depurador
ivanxuu
y yo estaba buscando el frente / reverso, classify, modelizeno parece funcionar.
Pysis
7

primero: gema instalar activesupport

require 'rubygems'
require 'active_support'
"FooBar".underscore.to_sym
ipsum
fuente
Debería serlo FooBar.to_s.underscore.to_sym, ya que estoy tratando de convertir una clase (que es una constante) en un símbolo, que luego puedo alimentar a Factory Girl . :)
Josh Glover
2

Esto es lo que busqué:

module MyModule
  module ClassMethods
    def class_to_sym  
      name_without_namespace = name.split("::").last
      name_without_namespace.gsub(/([^\^])([A-Z])/,'\1_\2').downcase.to_sym
    end
  end

  def self.included(base)
    base.extend(ClassMethods)
  end
end

class ThisIsMyClass
  include MyModule
end 

ThisIsMyClass.class_to_sym #:this_is_my_class
Louis Sayers
fuente
3
ActiveSupport tiene String#demodulizeque eliminará la pieza anterior ::.
amebe
@amoebe - gracias por la información. Sin embargo, depende de en qué trabajes; es posible que no estés trabajando en una aplicación de rieles (o incluso en una aplicación web).
Louis Sayers