Convertendo estojo de camelo em sublinhado em rubi


232

Existe alguma função pronta que converte Strings de caixa de camelo em string separada por sublinhado?

Eu quero algo como isto:

"CamelCaseString".to_underscore      

para retornar "camel_case_string".

...


43
FYI: letras minúsculas e sublinhado é "oficialmente" chamados caso de cobra
Andrew

3
É estranho ver "oficialmente" entre aspas e, no entanto, essa é a melhor maneira de descrevê-lo.
stevenspiel

Por alguma razão, vejo o método snakecase ausente. Rails 4.
Abram

Respostas:


362

O ActiveSupport do Rails adiciona sublinhado à String usando o seguinte:

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

Então você pode fazer coisas divertidas:

"CamelCase".underscore
=> "camel_case"

5
Se você mudar tr("-","_")para tr("- ","_")(espaço adicionado ao primeiro parâmetro), isso também transformará espaços em sublinhados. Além disso, acho que você nem precisa incluir self., ou pelo menos funciona para mim no Ruby 1.9.3.
Gus Shortz

6
require 'active_support/core_ext/string'
precisa saber é o seguinte

A função de sublinhado Active usa: github.com/rails/rails/blob/…
GreeKatrina

sublinhado é o método do Rails não ruby, consulte apidock.com/rails/String/underscore .
S.Yadav 23/09/19

1
@ S.Yadav true O método é um Rails, então você não pode chamar sublinhado por padrão, mas fornecendo o código usado e citando o Rails como fonte, essa resposta é boa para o ruby. Diz que você pode incluir o Rails ou apenas inclua esta função que a equipe de trilhos escreveu e testou.
Michael Gorman

99

Você pode usar

"CamelCasedName".tableize.singularize

Ou apenas

"CamelCasedName".underscore

Ambas as opções irão render "camel_cased_name". Você pode conferir mais detalhes aqui .


11
Isso faz parte da implementação do ActiveSupport :: Inflector, sem ela, você não pode usar essas extensões String (tente no console irb puro: "ThisCamelCaseString" .underscore, depois exija 'active_support / inflector' e tente novamente)
Evgenia Manolova

3
O rótulo do OP diz "ruby-on-rail"
Julien Lamarche

55

Implementação Ruby de uma linha:

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

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


2
como as outras soluções não são puramente rubi?
jrhicks

Oh, sh ... Obrigado - eu estava mais interessado em escrever do que em ler. Como resultado - os links no Rails me fizeram pensar que esses outros trechos eram específicos do Rails. Resposta alterada ...
kirushik 02/10/2009

1
há outro erro na minha edição e não parece que eu possa corrigi-lo. Aqui está o código corrigido: gist.github.com/4027440
Tim Harper

6
Você pode considerar /([^A-Z])([A-Z]+)/, em vez disso, manipular "ALLCAPS"-> em "allcaps"vez de"a_ll_ca_ps"
Nevir

4
Na verdade, é uma linha de 10!
22816 kristianp #

30

Existe um método embutido do Rails chamado 'underscore' que você pode usar para esse fim

"CamelCaseString".underscore #=> "camel_case_string" 

O método 'sublinhado' pode normalmente ser considerado como inverso de 'camelize'


1
método indefinido `sublinhado 'para" ... ": String
Dorian

5
É um método ActiveSupport
Dorian

20

Aqui está como o Rails faz isso :

   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
Melhor ter o operando como argumento do método do que invadir a classe String principal.
Pistos

1
Não concorde - é melhor tê-lo operando na classe como deveria ser; caso contrário, você terá que colocá-lo em um módulo e lembre-se de incluí-lo sempre que precisar.
Ghoti

1
Além disso, este método é parte do Rails 3 de cordas de qualquer maneira :)
Ghoti

2
Se eu pular esse debate - é melhor que ele invada a classe de string quando você o inclui =).
Evan Moran #


7

Confira o caso de cobras do Ruby Facets

Os seguintes casos são tratados, como mostrado abaixo:

"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

Não funciona com uma string com caracteres especiais. Ex:"Dumb Penguin's Egg".snakecase # => "dumb_penguin's_egg"
khiav reoy 15/06

6

Oneliner curto para CamelCases quando você tem espaços também incluídos (não funciona corretamente se você tiver uma palavra entre letras pequenas e iniciais):

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

  => "test_string"

1
underscorenão faz parte do ruby ​​#
31419

4

Caso alguém procure um caso em que ele precise aplicar sublinhado a string com espaços e desejar convertê-los em sublinhados, você pode usar algo como isto

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

Ou apenas use .parameterize ('_'), mas lembre-se de que este está obsoleto

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

1

Eu gostaria deste:

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

Remendo de macaco da Stringclasse. Há turmas que começam com duas ou mais letras em maiúsculas.


Você precisa mudar "\1_\2"para o '\1_\2'contrário, em "came\u0001_\u0002ase"vez "camel_case"de usar o Ruby 2.5 ... talvez outros também.
6 Dan Dan
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.