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".

...

Daniel Cukier
la source
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"
jrhicks
la source
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 .

abo-elleef
la source
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"

kirushik
la source
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»

Aaditi Jain
la source
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
Pesto
la source
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

Récepteur converti en étui serpent: http://rubydoc.info/gems/extlib/0.9.15/String#snake_case-instance_method

Il s'agit de la bibliothèque de support pour DataMapper et Merb. ( http://rubygems.org/gems/extlib )

def snake_case
  return downcase if match(/\A[A-Z]+\z/)
  gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
  gsub(/([a-z])([A-Z])/, '\1_\2').
  downcase
end

"FooBar".snake_case           #=> "foo_bar"
"HeadlineCNNNews".snake_case  #=> "headline_cnn_news"
"CNN".snake_case              #=> "cnn"
Mr Noir
la source
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
Abram
la source
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"
Andres Ehrenpreis
la source
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
Arman Petrosyan
la source
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.

rplaurindo
la source
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