Chuyển đổi trường hợp lạc đà sang trường hợp gạch dưới trong ruby


232

Có bất kỳ chức năng sẵn sàng nào để chuyển đổi chuỗi trường hợp lạc đà thành chuỗi phân tách gạch dưới không?

Tôi muốn một cái gì đó như thế này:

"CamelCaseString".to_underscore      

để trả về "camel_case_opes".

...


43
FYI: chữ thường và gạch dưới là "chính thức" được gọi là trường hợp rắn
Andrew

3
Thật lạ khi thấy "chính thức" trong dấu ngoặc kép, tuy nhiên, đó là cách tốt nhất để mô tả nó.
stevenspiel

Đối với một số lý do tôi thấy phương pháp snakecase bị thiếu. Đường ray 4.
Abram

Câu trả lời:


362

ActiveSupport của Rails thêm gạch dưới vào Chuỗi bằng cách sử dụng như sau:

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

Sau đó, bạn có thể làm công cụ thú vị:

"CamelCase".underscore
=> "camel_case"

5
Nếu bạn thay đổi tr("-","_")thành tr("- ","_")(không gian được thêm vào param đầu tiên), điều này cũng sẽ biến không gian thành dấu gạch dưới. Ngoài ra, tôi không nghĩ bạn thậm chí cần bao gồm self., hoặc ít nhất nó hoạt động với tôi theo Ruby 1.9.3.
Gus Shortz

6
require 'active_support/core_ext/string'
konsolebox

Hàm gạch dưới hoạt động sử dụng: github.com/rails/rails/blob/,
GreeKatrina

gạch dưới là phương pháp của Rails không ruby, xem apidock.com/rails/String/underscore .
S.Yadav

1
@ S.Yadav đúng phương thức là Rails vì vậy bạn không thể gọi gạch dưới theo mặc định, nhưng bằng cách cung cấp mã được sử dụng và trích dẫn đường ray vì nguồn câu trả lời này là một cách tốt cho ruby, Nó nói rằng bạn có thể bao gồm đường ray hoặc chỉ bao gồm chức năng này mà nhóm rails đã viết và đã thử nghiệm.
Michael Gorman

99

Bạn có thể dùng

"CamelCasedName".tableize.singularize

Hoặc chỉ

"CamelCasedName".underscore

Cả hai cách tùy chọn sẽ mang lại "camel_cased_name". Bạn có thể kiểm tra chi tiết hơn ở đây .


11
Đây là một phần của triển khai ActiveSupport :: Inflector, nếu không có nó, bạn không thể sử dụng các tiện ích mở rộng Chuỗi đó (thử trong bảng điều khiển irb thuần túy: "ThisCamelCaseString" .underscore, sau đó yêu cầu 'active_support / Inflector' và thử lại)
Evgenia Manolova

3
Nhãn của OP có ghi "ruby-on-rails"
Julien Lamarche

55

Thực hiện Ruby một lớp:

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

Vì thế "SomeCamelCase".to_underscore # =>"some_camel_case"


2
Làm thế nào là các giải pháp khác không phải là ruby ​​tinh khiết?
jrhicks

Oh, sh ... Cảm ơn - Tôi thích viết hơn là đọc. Kết quả là - các liên kết trên Rails khiến tôi nghĩ rằng những đoạn trích khác là dành riêng cho Rails. Thay đổi câu trả lời ...
kirushik

1
có một lỗi khác trong chỉnh sửa của tôi và có vẻ như tôi không thể sửa nó. Đây là mã được sửa: gist.github.com/4027440
Tim Harper

6
Bạn có thể muốn xem xét /([^A-Z])([A-Z]+)/thay vào đó, để xử lý "ALLCAPS"-> "allcaps"thay vì"a_ll_ca_ps"
Nevir

4
Đó thực sự là một lớp lót 10!
kristianp

30

Có một phương thức sẵn có Rails gọi là 'gạch dưới' mà bạn có thể sử dụng cho mục đích này

"CamelCaseString".underscore #=> "camel_case_string" 

Phương pháp 'gạch dưới' thường có thể được coi là nghịch đảo của 'camelize'


1
phương thức không xác định `gạch dưới 'cho" ... ": Chuỗi
Dorian

5
Đó là một phương thức ActiveSupport
Dorian

20

Đây là cách Rails thực hiện :

   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
Tốt hơn là có toán hạng làm đối số phương thức thay vì xâm chiếm lớp Chuỗi lõi.
Pistos

1
Đừng đồng ý - tốt hơn là để nó hoạt động trên lớp như nó phải, hoặc nếu không, bạn sẽ phải gắn nó vào một mô-đun và nhớ đưa nó vào bất cứ nơi nào bạn cần.
Ghoti

1
Ngoài ra, phương thức này cũng là một phần của chuỗi Rails 3 :)
Ghoti

2
Nếu tôi có thể tham gia vào cuộc tranh luận này - Tốt hơn là để nó xâm chiếm lớp chuỗi khi bạn đưa nó =).
Evan Moran

7

Người nhận chuyển đổi sang trường hợp con rắn: http://rubydoc.info/gems/extlib/0.9.15/String#snake_case-instance_method

Đây là thư viện Hỗ trợ cho DataMapper và 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"

7

Kiểm tra snakecase từ Ruby Facets

Các trường hợp sau đây được xử lý, như được thấy dưới đây:

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

Từ: https://github.com/rubyworks/facets/blob/master/lib/core/facets/opes/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ó không hoạt động với một chuỗi có ký tự đặc biệt. Vd:"Dumb Penguin's Egg".snakecase # => "dumb_penguin's_egg"
khiav reoy

6

Oneliner ngắn cho CamelCase khi bạn cũng có khoảng trắng (không hoạt động chính xác nếu bạn có một từ xen kẽ với chữ cái bắt đầu nhỏ):

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

  => "test_string"

1
underscorekhông phải là một phần của ruby
dft

4

Trong trường hợp ai đó đang tìm kiếm trường hợp khi anh ta cần áp dụng dấu gạch dưới cho chuỗi có khoảng trắng và muốn chuyển đổi chúng thành dấu gạch dưới, bạn cũng có thể sử dụng cái gì đó như thế này

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

Hoặc chỉ sử dụng .parameterize ('_') nhưng hãy nhớ rằng cái này không được dùng nữa

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

1

Tôi muốn điều này:

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

Khỉ vá Stringlớp. Có những lớp bắt đầu bằng hai hoặc nhiều chữ cái viết hoa.


Bạn cần thay đổi "\1_\2"thành '\1_\2'nếu không bạn sẽ kết thúc "came\u0001_\u0002ase"thay vì "camel_case"Ruby 2.5 ... có thể cả những người khác nữa.
6ft Dan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.