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

...

Daniel Cukier
sumber
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"
Jrhicks
sumber
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 .

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

Kirushik
sumber
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'

Aaditi Jain
sumber
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
pesto
sumber
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

Penerima dikonversi menjadi kotak ular: http://rubydoc.info/gems/extlib/0.9.15/String#snake_case-instance_method

Ini adalah perpustakaan Dukungan untuk DataMapper dan 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"
Tuan hitam
sumber
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
Abram
sumber
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"
Andres Ehrenpreis
sumber
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
Arman Petrosyan
sumber
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.

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