ฉันจะแปลงชื่อคลาส Ruby เป็นสัญลักษณ์ที่คั่นด้วยขีดล่างได้อย่างไร


99

ฉันจะเปลี่ยนชื่อคลาสFooBarเป็นสัญลักษณ์โดยทางโปรแกรมได้:foo_barอย่างไร เช่นอะไรทำนองนี้ แต่ที่จับอูฐอย่างถูกต้อง?

FooBar.to_s.downcase.to_sym

คำตอบ:


145

Rails มาพร้อมกับวิธีการที่เรียกunderscoreว่าจะช่วยให้คุณสามารถแปลงสตริง CamelCased เป็นสตริง underscore_separated ดังนั้นคุณอาจสามารถทำได้:

FooBar.name.underscore.to_sym

แต่คุณจะต้องติดตั้ง ActiveSupport เพื่อทำเช่นนั้นตามที่ ipsum กล่าว

หากคุณไม่ต้องการติดตั้ง ActiveSupport เพียงเพื่อสิ่งนั้นคุณสามารถปะลิงunderscoreเข้ากับStringตัวเองได้ (ฟังก์ชันขีดล่างถูกกำหนดไว้ใน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
ขอบคุณ. ฉันกลัวว่านี่เป็นส่วนขยาย Rails :) ไม่ต้องกังวลเพราะฉันใช้ Rails จริงๆ
Josh Glover

2
จากนั้นคุณควรติดแท็กคำถามของคุณตามนั้น ให้ฉันทำเพื่อคุณ ...
kikito

5
ไม่ไม่ใช่ ActiveRecord ActiveSupport
Rein Henrichs

ที่จริงให้ฉันเปลี่ยน
kikito

2
วิธีทำย้อนกลับ?
user1406062

73

ราง 4 .model_name

ใน Rails 4 จะส่งคืนไฟล์ ActiveModel::Nameอ็อบเจ็กต์ที่มีแอตทริบิวต์ "semantic" ที่มีประโยชน์มากมายเช่น:

FooBar.model_name.param_key
#=> "foo_bar"

FooBar.model_name.route_key
#=> "foo_bars"

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

ดังนั้นคุณควรใช้อย่างใดอย่างหนึ่งหากตรงกับความหมายที่คุณต้องการซึ่งเป็นไปได้ว่าในกรณีนี้ ข้อดี:

  • เข้าใจรหัสของคุณง่ายขึ้น
  • แอปของคุณจะยังคงใช้งานได้แม้ในกรณี (ไม่น่าจะเป็นไปได้) ที่ Rails ตัดสินใจเปลี่ยนหลักการตั้งชื่อ

BTW humanมีข้อได้เปรียบของการรับรู้ I18N


model_nameยังใช้ได้กับวัตถุเช่น เช่น: foo_bar.model_name. หากคุณต้องการให้รายการทั้งหมดเขียนfoo_bar.model_name.inspectในคอนโซลรางหรือดีบักเกอร์ของคุณ
ivanxuu

และผมกำลังมองหาที่อยู่ตรงข้าม / ย้อนกลับclassify, modelizeไม่ได้ดูเหมือนจะทำงาน
Pysis

9

อันดับแรก: การสนับสนุนการติดตั้งอัญมณี

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

ควรจะเป็นFooBar.to_s.underscore.to_symเพราะฉันกำลังพยายามแปลงคลาส (ซึ่งเป็นค่าคงที่) เป็นสัญลักษณ์ซึ่งฉันสามารถป้อนให้กับFactory Girlได้ :)
Josh Glover

2

นี่คือสิ่งที่ฉันทำเพื่อ:

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
ActiveSupport มีซึ่งจะลบส่วนหนึ่งก่อนString#demodulize ::
amoebe

@amoebe - ขอบคุณสำหรับข้อมูล ขึ้นอยู่กับว่าคุณกำลังทำงานอะไรอยู่ - คุณอาจไม่ได้ทำงานบนแอพพลิเคชั่นราง (หรือแม้แต่เว็บแอพ)
Louis Sayers
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.