ทับทิมแปลงชื่อคลาสในสตริงเป็นคลาสจริง


89

ฉันจะเรียกคลาสจากสตริงที่มีชื่อคลาสนั้นอยู่ข้างในได้อย่างไร (ฉันเดาว่าฉันสามารถทำกรณี / เมื่อ แต่มันดูน่าเกลียด)

เหตุผลที่ฉันถามคือเพราะฉันใช้acts_as_commentableปลั๊กอินและอื่น ๆ และสิ่งเหล่านี้เก็บ commentable_type เป็นคอลัมน์ ฉันต้องการที่จะเรียกชั้นเรียนที่มีความคิดเห็นเป็นพิเศษเพื่อทำสิ่งfind(commentable_id)นั้น

ขอบคุณ.

คำตอบ:


133

ฉันคิดว่าสิ่งที่คุณต้องการคือ constantize

นั่นคือโครงสร้าง RoR ไม่รู้ว่ามีแกนทับทิมหรือเปล่า


สมบูรณ์แบบนั่นคือสิ่งที่ฉันกำลังมองหา
ไม่เรียงลำดับ

40
สำหรับ Ruby Module.const_getธรรมดาที่คุณต้องการใช้ ประโยชน์ของการconstantizeเป็นที่ทำงานแม้จะมี namespaces ซ้อนกันอย่างลึกซึ้งเพื่อให้คุณสามารถทำ'Functional::Collections::LazyList'.constantizeและได้รับ LazyList ระดับจากคอลเลกชันโมดูลในโมดูลการทำงานในขณะที่มีคุณจะต้องทำสิ่งที่ชอบconst_get 'Functional::Collections::LazyList'.split('::').reduce(Module, :const_get)
Chuck


35

กำหนดสตริงให้เรียกแยกประเภทเพื่อสร้างชื่อคลาส (ยังคงเป็นสตริง) จากนั้นเรียกค่าคงที่เพื่อพยายามค้นหาและส่งคืนค่าคงที่ของชื่อคลาส (โปรดทราบว่าชื่อคลาสเป็นค่าคงที่ )

some_string.classify.constantize

10
คุณควรใช้ camelize แทนการจัดประเภทเนื่องจากการจัดประเภทมีไว้สำหรับชื่อตารางและไม่สามารถจัดการกับพหูพจน์ได้เป็นอย่างดี
Peter Brown

2
คำตอบของคุณมีค่ามาก แต่คุณควรใช้ "titleize" สำหรับชื่อตารางที่มีช่องว่างและลบช่องว่างออกจากสตริงเพื่อให้ชื่อคลาสเต็ม
SSR

22

ฉันรู้ว่านี่เป็นคำถามเก่า แต่ฉันแค่อยากจะทิ้งบันทึกนี้ไว้มันอาจจะเป็นประโยชน์สำหรับคนอื่น ๆ

ใน Ruby ธรรมดาModule.const_getสามารถหาค่าคงที่ซ้อนกันได้ ตัวอย่างเช่นมีโครงสร้างดังต่อไปนี้:

module MyModule
  module MySubmodule
    class MyModel
    end
  end
end

คุณสามารถใช้งานได้ดังนี้:

Module.const_get("MyModule::MySubmodule::MyModel")
MyModule.const_get("MySubmodule")
MyModule::MySubmodule.const_get("MyModel")

7

เมื่อ ActiveSupport ใช้ได้ (เช่นใน Rails): String#constantizeหรือว่าเป็นString#safe_constantize"ClassName".constantize

ในทับทิมบริสุทธิ์โดยทั่วไปModule#const_getObject.const_get("ClassName")

ในทับทิมล่าสุดทั้งคู่ทำงานกับค่าคงที่ที่ซ้อนกันในโมดูลเช่นในObject.const_get("Outer::Inner").


6

หากคุณต้องการแปลงสตริงเป็นชื่อคลาสแอคทูออลเพื่อเข้าถึงโมเดลหรือคลาสอื่น ๆ

str = "group class"

> str.camelize.constantize 'or'
> str.classify.constantize 'or'
> str.titleize.constantize

Example :
  def call_me(str)
    str.titleize.gsub(" ","").constantize.all
  end

Call method : call_me("group class")

Result:
  GroupClass Load (0.7ms) SELECT `group_classes`.* FROM `group_classes`
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.