2009-10-02 9 views
178

Y at-il une fonction prête qui convertit les ficelles de chameau en chaîne séparée par un trait de soulignement?Conversion chameau à underscore case en ruby ​​

Je veux quelque chose comme ceci:

"CamelCaseString".to_underscore  

pour revenir "camel_case_string".

...

+35

Pour votre information: minuscule et underscored est appelé serpent « officiellement » case – Andrew

+3

Il est étrange de voir "officiellement" entre guillemets, et pourtant, c'est la meilleure façon de le décrire. –

Répondre

299

Rails' ActiveSupport adds tiret de soulignement la chaîne en utilisant les éléments suivants:

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 

Ensuite, vous pouvez faire des choses amusantes:

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

Si vous changez 'tr (" - "," _ ")' en 'tr (" - "," _ ")' (espace ajouté au premier param), cela transformera aussi les espaces en caractères de soulignement. En outre, je ne pense pas que vous avez même besoin d'inclure «self», ou au moins cela fonctionne pour moi sous Ruby 1.9.3. –

+3

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

16

Voici comment 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 
+0

Mieux vaut avoir l'opérande comme argument de méthode plutôt que d'envahir la classe String principale. – Pistos

+1

Je ne suis pas d'accord - mieux vaut le faire fonctionner comme il le devrait dans la classe, sinon vous devrez le coller dans un module et n'oubliez pas de l'inclure là où vous en aurez besoin. – Ghoti

+1

Aussi cette méthode fait partie des chaînes de Rails 3 de toute façon :) – Ghoti

45

One-liner mise en œuvre 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 

Alors "SomeCamelCase".to_underscore # =>"some_camel_case"

+2

comment les autres solutions ne sont-elles pas du pur rubis? – jrhicks

+0

Oh, sh ... Merci - j'étais plus intéressé par l'écriture que par la lecture. En conséquence, les liens sur Rails m'ont fait penser que ces autres extraits étaient spécifiques à Rails. Changement de réponse ... – kirushik

+1

Il y a une autre erreur dans ma modification, et il ne semble pas que je puisse la réparer. Voici le code corrigé: https://gist.github.com/4027440 –

61

Vous pouvez utiliser

"CamelCasedName".tableize.singularize 

Ou

"CamelCasedName".underscore 

Les deux façons d'options donneront "camel_cased_name". Vous pouvez vérifier plus de détails here.

+8

Cela fait partie de l'implémentation d'ActiveSupport :: Inflector, sans elle, vous ne pouvez pas utiliser ces extensions String (essayez dans pure irb console: "ThisCamelCaseString" .underscore, puis require 'active_support/inflector' et réessayez) –

+5

Downvoted parce que ce n'est pas simple rubis. – Papipo

25

Il existe une méthode intégrée Rails appelée 'underscore' que vous pouvez utiliser à cet effet

"CamelCaseString".underscore #=> "camel_case_string" 

La méthode 'underscore' peut généralement être considérée comme inverse de 'camelize'

+0

Méthode non définie 'underscore 'pour" ... ": String – Dorian

+2

C'est une méthode ActiveSupport – Dorian

6

Check out snake case de Ruby Facets

Les cas suivants sont traités, comme on le voit ci-dessous:

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

De: 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

Je voudrais ceci:

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 

patch Singe de String classe. Il y a des classes qui commencent par deux lettres ou plus en majuscules.

3

court oneliner pour camelCase lorsque vous avez des espaces également inclus (si vous n'avez fonctionnera pas correctement un mot inbetween avec un petit départ lettre):

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

    => "test_string"