Conversion de l'étui camel en étui souligné en rubis


232

Existe-t-il une fonction prête à convertir les chaînes de cas de chameau en chaîne séparée par des traits de soulignement?

Je veux quelque chose comme ça:

"CamelCaseString".to_underscore      

pour retourner "camel_case_string".

...


43
FYI: minuscule et souligné est "officiellement" appelé cas de serpent
Andrew

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

Pour une raison quelconque, je vois la méthode snakecase manquante. Rails 4.
Abram

Réponses:


363

ActiveSupport de Rails ajoute un trait de soulignement à la chaîne en utilisant ce qui suit:

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 trucs amusants:

"CamelCase".underscore
=> "camel_case"

5
Si vous passez tr("-","_")à tr("- ","_")(espace ajouté au premier paramètre), cela transformera également les espaces en traits de soulignement. De plus, je ne pense pas que vous ayez même besoin d'inclure self., ou du moins cela fonctionne pour moi sous Ruby 1.9.3.
Gus Shortz

6
require 'active_support/core_ext/string'
konsolebox

La fonction de soulignement utilise Active: github.com/rails/rails/blob/…
GreeKatrina

le trait de soulignement est la méthode de Rails not ruby, voir apidock.com/rails/String/underscore .
S.Yadav

1
@ S.Yadav true, la méthode est un Rails, vous ne pouvez donc pas appeler de soulignement par défaut, mais en fournissant le code utilisé et en citant les rails comme source, cette réponse est bonne pour ruby, elle dit que vous pouvez inclure des rails, ou tout simplement inclure cette fonction que l'équipe rails a écrite et testée.
Michael Gorman

99

Vous pouvez utiliser

"CamelCasedName".tableize.singularize

Ou juste

"CamelCasedName".underscore

Les deux options donneront des résultats "camel_cased_name". Vous pouvez vérifier plus de détails ici .


11
Cela fait partie de l'implémentation d'ActiveSupport :: Inflector, sans lui, vous ne pouvez pas utiliser ces extensions de chaîne (essayez dans la console pure irb: "ThisCamelCaseString" .underscore, puis exigez 'active_support / inflector' et réessayez)
Evgenia Manolova

3
Le label de l'OP dit "rubis sur rails"
Julien Lamarche

55

Implémentation Ruby à une ligne:

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 rubis pur?
jrhicks

Oh, sh ... Merci - j'étais plus intéressé par l'écriture que par la lecture. Par conséquent, les liens sur Rails m'ont fait penser que ces autres extraits étaient spécifiques à Rails. Réponse
modifiée

1
il y a une autre erreur dans ma modification, et il ne semble pas que je puisse la corriger. Voici le code corrigé: gist.github.com/4027440
Tim Harper

6
Vous voudrez peut-être envisager /([^A-Z])([A-Z]+)/plutôt de gérer "ALLCAPS"-> "allcaps"au lieu de"a_ll_ca_ps"
Nevir

4
C'est en fait un 10 lignes!
kristianp

30

Il existe une méthode intégrée de Rails appelée «souligné» que vous pouvez utiliser à cette fin

"CamelCaseString".underscore #=> "camel_case_string" 

La méthode de «soulignement» peut généralement être considérée comme l'inverse de «camelize»


1
méthode non définie `underscore 'pour" ... ": String
Dorian

5
C'est une méthode ActiveSupport
Dorian

20

Voici comment Rails procède :

   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

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

1
Ne soyez pas d'accord - mieux vaut le faire fonctionner sur la classe comme il se doit, sinon vous devrez le coller dans un module et n'oubliez pas de l'inclure partout où vous en aurez besoin.
Ghoti

1
Cette méthode fait également partie des chaînes de Rails 3 de toute façon :)
Ghoti

2
Si je peux me lancer dans ce débat - Mieux vaut l'avoir envahi la classe de chaîne lorsque vous l'incluez =).
Evan Moran


7

Découvrez la snakecase de Ruby Facets

Les cas suivants sont traités, comme indiqué 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

Cela ne fonctionne pas avec une chaîne avec un caractère spécial. Ex:"Dumb Penguin's Egg".snakecase # => "dumb_penguin's_egg"
khiav reoy

6

Oneliner court pour CamelCases lorsque vous avez également des espaces (ne fonctionne pas correctement si vous avez un mot entre les deux avec une petite lettre de départ):

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

  => "test_string"

1
underscorene fait pas partie de ruby
dft

5

Dans le cas où quelqu'un cherche un cas quand il a besoin d'appliquer un trait de soulignement à une chaîne avec des espaces et que vous souhaitez les convertir en traits de soulignement, vous pouvez également utiliser quelque chose comme ceci

'your String will be converted To underscore'.parameterize.underscore
#your_string_will_be_converted_to_underscore

Ou utilisez simplement .parameterize ('_') mais gardez à l'esprit que celui-ci est obsolète

'your String will be converted To underscore'.parameterize('_')
#your_string_will_be_converted_to_underscore

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 de singe de Stringclasse. Il existe des classes qui commencent par deux lettres ou plus en majuscules.


Vous devez changer "\1_\2"pour '\1_\2'sinon vous vous retrouverez avec "came\u0001_\u0002ase"au lieu "camel_case"de Ruby 2.5 ... peut-être d'autres aussi.
6 pieds Dan
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.