2009-10-02 12 views
178

¿Hay alguna función lista que convierta Cadenas de caja de camello en una cuerda separada de subrayado?Conversión de la caja de camello a la caja de subrayado en rubí

Quiero algo como esto:

"CamelCaseString".to_underscore  

para volver "camel_case_string".

...

+35

FYI: minúsculas y subrayado es "oficialmente" llamada serpiente case – Andrew

+3

Es extraño ver "oficialmente" entre comillas, y sin embargo, esa es la mejor manera de describirlo. –

Respuesta

299

Rails' ActiveSupport adds subrayan a la cadena utilizando la siguiente:

class String 
    def underscore 
    self.gsub(/::/, '/'). 
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). 
    gsub(/([a-z\d])([A-Z])/,'\1_\2'). 
    tr("-", "_"). 
    downcase 
    end 
end 

entonces usted puede hacer cosas divertidas:

"CamelCase".underscore 
=> "camel_case" 
+5

Si cambia 'tr (" - "," _ ")' a 'tr (" - "," _ ")' (espacio agregado al primer parámetro), esto también convertirá los espacios en guiones bajos. Además, no creo que necesites incluir 'self', o al menos me funciona con Ruby 1.9.3. –

+3

'require 'active_support/core_ext/string'' – konsolebox

16

Así es como Rails does it:

def underscore(camel_cased_word) 
    camel_cased_word.to_s.gsub(/::/, '/'). 
     gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). 
     gsub(/([a-z\d])([A-Z])/,'\1_\2'). 
     tr("-", "_"). 
     downcase 
    end 
aplicación
+0

Es mejor tener el operando como un argumento de método en lugar de invadir la clase String central. – Pistos

+1

No estoy de acuerdo, es mejor tenerlo funcionando en la clase como debería ser, o de lo contrario tendrá que colocarlo en un módulo y no olvide incluirlo donde lo necesite. – Ghoti

+1

También este método forma parte de las cadenas de Rails 3 :) – Ghoti

45

de una sola línea Ruby:

class String 
    # ruby mutation methods have the expectation to return self if a mutation occurred, nil otherwise. (see http://www.ruby-doc.org/core-1.9.3/String.html#method-i-gsub-21) 
    def to_underscore! 
    gsub!(/(.)([A-Z])/,'\1_\2') 
    downcase! 
    end 

    def to_underscore 
    dup.tap { |s| s.to_underscore! } 
    end 
end 

Así "SomeCamelCase".to_underscore # =>"some_camel_case"

+2

¿cómo son las otras soluciones no rubí puro? – jrhicks

+0

Oh, sh ... Gracias - Estaba más interesado en escribir que en leer. Como resultado, los enlaces en Rails me hicieron pensar que esos otros fragmentos son específicos de Rails. Respuesta modificada ... – kirushik

+1

hay otro error en mi edición, y no parece que pueda solucionarlo. Aquí está el código corregido: https://gist.github.com/4027440 –

61

Puede utilizar

"CamelCasedName".tableize.singularize 

O simplemente

"CamelCasedName".underscore 

Ambas formas opciones producirán los "camel_cased_name". Puede consultar más detalles here.

+8

Esto es parte de la implementación de ActiveSupport :: Inflector, sin él, no puede usar esas extensiones de cadena (intente en pura consola irb: "ThisCamelCaseString" .underscore, luego requiera 'active_support/inflector' y vuelva a intentarlo) –

+5

Downvoted porque esto no es simple rubí. – Papipo

25

Hay un método incorporado rieles llamado 'guión' que se puede utilizar para este propósito

"CamelCaseString".underscore #=> "camel_case_string" 

El método 'guión' normalmente se puede considerar como inversa de 'camelize'

+0

método undefined 'subrayado 'para" ... ": String – Dorian

+2

Es un método ActiveSupport – Dorian

6

Salida snakecase de Ruby Facets

Los siguientes casos son manejados, como se ve a continuación:

"SnakeCase".snakecase   #=> "snake_case" 
"Snake-Case".snakecase  #=> "snake_case" 
"Snake Case".snakecase  #=> "snake_case" 
"Snake - Case".snakecase #=> "snake_case" 

Desde: https://github.com/rubyworks/facets/blob/master/lib/core/facets/string/snakecase.rb

class String 

    # Underscore a string such that camelcase, dashes and spaces are 
    # replaced by underscores. This is the reverse of {#camelcase}, 
    # albeit not an exact inverse. 
    # 
    # "SnakeCase".snakecase   #=> "snake_case" 
    # "Snake-Case".snakecase  #=> "snake_case" 
    # "Snake Case".snakecase  #=> "snake_case" 
    # "Snake - Case".snakecase #=> "snake_case" 
    # 
    # Note, this method no longer converts `::` to `/`, in that case 
    # use the {#pathize} method instead. 

    def snakecase 
    #gsub(/::/, '/'). 
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). 
    gsub(/([a-z\d])([A-Z])/,'\1_\2'). 
    tr('-', '_'). 
    gsub(/\s/, '_'). 
    gsub(/__+/, '_'). 
    downcase 
    end 

    # 
    alias_method :underscore, :snakecase 

    # TODO: Add *separators to #snakecase, like camelcase. 

end 
1

Me gustaría que esta: parche

class String 

    # \n returns the capture group of "n" index 
    def snikize 
    self.gsub(/::/, '/') 
    .gsub(/([a-z\d])([A-Z])/, "\1_\2") 
    .downcase 
    end 

    # or 

    def snikize 
    self.gsub(/::/, '/') 
    .gsub(/([a-z\d])([A-Z])/) do 
     "#{$1}_#{$2}" 
    end 
    .downcase 
    end 

end 

mono de String clase. Hay clases que comienzan con dos o más letras en mayúsculas.

3

oneliner corto para CamelCases cuando haya espacios también se incluye (no funciona correctamente si usted tiene una palabra entre medio con una pequeña partida letras):

a = "Test String" 
a.gsub(' ', '').underscore 

    => "test_string" 
Cuestiones relacionadas