Bagaimana cara mengonversi nama kelas Ruby menjadi simbol yang dipisahkan garis bawah?


97

Bagaimana cara saya secara terprogram mengubah nama kelas FooBar,, menjadi simbol :foo_bar,? Misalnya sesuatu seperti ini, tapi itu menangani kotak unta dengan benar?

FooBar.to_s.downcase.to_sym

Jawaban:


143

Rails dilengkapi dengan metode underscoreyang memungkinkan Anda untuk mengubah string CamelCased menjadi string underscore_separated. Jadi, Anda mungkin bisa melakukan ini:

FooBar.name.underscore.to_sym

Tetapi Anda harus menginstal ActiveSupport hanya untuk melakukan itu, seperti yang dikatakan ipsum.

Jika Anda tidak ingin menginstal ActiveSupport hanya untuk itu, Anda dapat melakukan monkey-patch underscoreke Stringdiri Anda sendiri (fungsi garis bawah ditentukan di ActiveSupport :: Inflector ):

class String
  def underscore
    word = self.dup
    word.gsub!(/::/, '/')
    word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
    word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
    word.tr!("-", "_")
    word.downcase!
    word
  end
end

1
Terima kasih. Saya takut ini adalah ekstensi Rails. :) Jangan khawatir, karena saya sebenarnya menggunakan Rails.
Josh Glover

2
Maka Anda seharusnya telah menandai pertanyaan Anda dengan tepat. Di sini, biarkan saya melakukannya untuk Anda ...
kikito

5
Tidak, bukan ActiveRecord. ActiveSupport.
Rein Henrichs

Memang, izinkan saya mengubahnya
kikito

2
bagaimana melakukan kebalikannya?
pengguna1406062

73

Rel 4 .model_name

Di Rails 4, ia mengembalikan ActiveModel::Nameobjek yang berisi lebih banyak atribut "semantik" yang berguna seperti:

FooBar.model_name.param_key
#=> "foo_bar"

FooBar.model_name.route_key
#=> "foo_bars"

FooBar.model_name.human
#=> "Foo bar"

Jadi Anda harus menggunakan salah satu dari mereka jika cocok dengan makna yang Anda inginkan, yang kemungkinan besar terjadi. Keuntungan:

  • lebih mudah untuk memahami kode Anda
  • aplikasi Anda akan tetap berfungsi bahkan dalam peristiwa (tidak mungkin) ketika Rails memutuskan untuk mengubah konvensi penamaan.

BTW, humanmemiliki keuntungan karena sadar I18N.


model_namejuga berfungsi untuk objek contoh. Ex: foo_bar.model_name. Jika Anda ingin daftar lengkap tulis foo_bar.model_name.inspectdi konsol rel atau debugger Anda
ivanxuu

dan saya sedang mencari sebaliknya / terbalik, classify, modelizetampaknya tidak bekerja.
Pysis

7

pertama: gem instal aktif dukungan

require 'rubygems'
require 'active_support'
"FooBar".underscore.to_sym

Seharusnya FooBar.to_s.underscore.to_sym, karena saya mencoba mengonversi kelas (yang merupakan konstanta) menjadi simbol, yang kemudian dapat saya berikan ke Factory Girl . :)
Josh Glover

2

Inilah yang saya lakukan:

module MyModule
  module ClassMethods
    def class_to_sym  
      name_without_namespace = name.split("::").last
      name_without_namespace.gsub(/([^\^])([A-Z])/,'\1_\2').downcase.to_sym
    end
  end

  def self.included(base)
    base.extend(ClassMethods)
  end
end

class ThisIsMyClass
  include MyModule
end 

ThisIsMyClass.class_to_sym #:this_is_my_class

3
Memiliki ActiveSupport String#demodulizeyang akan menghapus part sebelumnya ::.
amoebe

@ amoebe - terima kasih atas infonya. Tergantung pada apa yang Anda kerjakan - Anda mungkin tidak mengerjakan aplikasi rel (atau bahkan aplikasi web).
Louis Sayers
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.