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.