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

...

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

abo-elleef
fonte
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"

kirushik
fonte
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'

Aaditi Jain
fonte
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
Pesto
fonte
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

Receptor convertido em caso de cobra: http://rubydoc.info/gems/extlib/0.9.15/String#snake_case-instance_method

Esta é a biblioteca de suporte do DataMapper e 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"
Senhor preto
fonte
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
Abram
fonte
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"
Andres Ehrenpreis
fonte
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
Arman Petrosyan
fonte
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.

rplaurindo
fonte
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