Konversi kasing unta untuk menggarisbawahi kasing di ruby


232

Apakah ada fungsi siap yang mengubah Strings case unta menjadi string dipisahkan garis bawah?

Saya ingin sesuatu seperti ini:

"CamelCaseString".to_underscore      

untuk mengembalikan "camel_case_string".

...


43
FYI: huruf kecil dan garis bawah adalah "secara resmi" disebut case snake
Andrew

3
Sungguh aneh melihat "secara resmi" dalam tanda kutip, namun, itulah cara terbaik untuk menggambarkannya.
stevenspiel

Untuk beberapa alasan saya melihat metode snakecase hilang. Rails 4.
Abram

Jawaban:


362

ActiveSupport Rails menambahkan garis bawah pada String menggunakan yang berikut ini:

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

Maka Anda dapat melakukan hal-hal menyenangkan:

"CamelCase".underscore
=> "camel_case"

5
Jika Anda mengubah tr("-","_")ke tr("- ","_")(spasi ditambahkan ke param pertama), ini juga akan mengubah spasi menjadi garis bawah. Juga, saya pikir Anda bahkan tidak perlu memasukkan self., atau setidaknya itu berfungsi untuk saya di Ruby 1.9.3.
Gus Shortz

6
require 'active_support/core_ext/string'
konsolebox

Fungsi garis bawah Penggunaan aktif: github.com/rails/rails/blob/…
GreeKatrina

underscore adalah metode Rails yang tidak ruby, lihat apidock.com/rails/String/underscore .
S.Yadav

1
@ S. Yadav true metode ini adalah Rails sehingga Anda tidak dapat memanggil garis bawah secara default, tetapi dengan memberikan kode yang digunakan dan mengutip rails sebagai sumber, jawaban ini bagus untuk ruby, Dikatakan Anda dapat memasukkan rails, atau hanya termasuk fungsi ini yang ditulis dan diuji oleh tim rel.
Michael Gorman

99

Kamu bisa memakai

"CamelCasedName".tableize.singularize

Atau hanya

"CamelCasedName".underscore

Kedua opsi cara akan menghasilkan "camel_cased_name". Anda dapat memeriksa detail lebih lanjut di sini .


11
Ini adalah bagian dari implementasi ActiveSupport :: Inflector, tanpa itu, Anda tidak dapat menggunakan ekstensi String tersebut (coba di konsol irb murni: "ThisCamelCaseString" .underscore, lalu minta 'active_support / inflector' dan coba lagi)
Evgenia Manolova

3
Label OP mengatakan "ruby-on-rails"
Julien Lamarche

55

Implementasi Ruby satu lapis:

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

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


2
bagaimana solusi lain bukan ruby ​​murni?
jrhicks

Oh, s ... Terima kasih - Saya lebih tertarik menulis daripada membaca. Sebagai hasilnya - tautan pada Rails membuat saya berpikir bahwa snippet lainnya khusus untuk Rails. Jawaban yang diubah ...
Kirushik

1
ada kesalahan lain dalam edit saya, dan tampaknya saya tidak bisa memperbaikinya. Berikut adalah kode yang diperbaiki: gist.github.com/4027440
Tim Harper

6
Anda mungkin ingin mempertimbangkan /([^A-Z])([A-Z]+)/, untuk menangani "ALLCAPS"-> "allcaps"alih-alih"a_ll_ca_ps"
Nevir

4
Itu sebenarnya 10-liner!
kristianp

30

Ada metode inbuilt Rails yang disebut 'garis bawah' yang dapat Anda gunakan untuk tujuan ini

"CamelCaseString".underscore #=> "camel_case_string" 

Metode 'garis bawah' biasanya dapat dianggap sebagai kebalikan dari 'camelize'


1
metode tidak terdefinisi `garis bawah 'untuk" ... ": String
Dorian

5
Ini adalah metode ActiveSupport
Dorian

20

Begini cara Rails melakukannya :

   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
Lebih baik memiliki operan sebagai argumen metode daripada menginvasi kelas String inti.
Pistos

1
Jangan setuju - lebih baik mengoperasikannya di kelas seperti seharusnya, atau Anda harus memasukkannya ke dalam modul dan ingat untuk memasukkannya di mana pun Anda membutuhkannya.
Ghoti

1
Juga metode ini adalah bagian dari string Rails 3 :)
Ghoti

2
Jika saya bisa masuk ke debat ini - Lebih baik menginvasi kelas string ketika Anda memasukkannya =).
Evan Moran


7

Lihat snakecase dari Ruby Facets

Kasus-kasus berikut ditangani, seperti yang terlihat di bawah ini:

"SnakeCase".snakecase         #=> "snake_case"
"Snake-Case".snakecase        #=> "snake_case"
"Snake Case".snakecase        #=> "snake_case"
"Snake  -  Case".snakecase    #=> "snake_case"

Dari: 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

Itu tidak bekerja dengan string dengan karakter khusus. Contoh:"Dumb Penguin's Egg".snakecase # => "dumb_penguin's_egg"
khiav reoy

6

Oneliner singkat untuk CamelCases ketika Anda memiliki spasi juga termasuk (tidak berfungsi dengan benar jika Anda memiliki kata peralihan dengan huruf awal kecil):

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

  => "test_string"

1
underscorebukan bagian dari ruby
dft

4

Jika seseorang mencari kasus ketika dia perlu menerapkan garis bawah untuk merangkai dengan spasi dan ingin mengubahnya menjadi garis bawah juga Anda dapat menggunakan sesuatu seperti ini

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

Atau cukup gunakan .parameterize ('_') tetapi perlu diingat bahwa ini sudah usang

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

1

Saya ingin ini:

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 Stringkelas monyet . Ada kelas yang dimulai dengan dua atau lebih huruf dalam huruf besar.


Anda perlu mengubah "\1_\2"agar '\1_\2'Anda tidak akan berakhir dengan "came\u0001_\u0002ase"bukannya "camel_case"Ruby 2.5 ... mungkin orang lain juga.
6ft Dan
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.