ลองนึกภาพคำถามที่อาจเป็น "รอดำเนินการ" "อนุมัติ" หรือ "ติดธง" หรือหมายเลขโทรศัพท์ที่เป็น "บ้าน" "ที่ทำงาน" "มือถือ" หรือ "แฟกซ์" (หากเป็นปี 1982)
บางรุ่นต้องการข้อมูลประเภทนี้ คุณลักษณะที่สามารถมีค่าต่างๆ ได้เพียงไม่กี่ค่าเท่านั้น และชุดค่านั้นแทบไม่เคยเปลี่ยนแปลง
เป็นสถานการณ์ที่หากเป็น Ruby ธรรมดา คุณจะใช้สัญลักษณ์
คุณสามารถสร้างโมเดล PhoneNumberType หรือ QuestionStatus และ belongs_to
ที่จะรักษาค่านิยมเหล่านี้ไว้ แต่นั่นก็ดูไม่คุ้มค่า คุณสามารถเก็บมันไว้ในไฟล์ yaml ได้ แต่ตอนนี้คุณต้องมองหาที่อื่นเพื่อค้นหาว่าวัตถุของคุณทำอะไรได้บ้าง
ใน 4.1 Rails ได้แก้ปัญหานี้ด้วย ActiveRecord enums
ค่าสองสามค่าในโมเดล
ActiveRecord enums ค่อนข้างง่าย คุณให้โมเดลของคุณเป็น integer
คอลัมน์:
bin/rails g model phone number:string phone_number_type:integer
ระบุค่าที่แอตทริบิวต์สามารถรับได้:
class Phone < ActiveRecord::Base
enum phone_number_type: [:home, :office, :mobile, :fax]
end
และตอนนี้คุณสามารถจัดการกับสตริงแทนที่จะเป็นตัวเลขได้
แทนสิ่งนี้:
irb(main):001:0> Phone.first.phone_number_type
=> 3
คุณจะเห็นสิ่งนี้:
irb(main):002:0> Phone.first.phone_number_type
=> "fax"
คุณสามารถ เปลี่ยน แอตทริบิวต์นั้นโดยใช้สตริงหรือ ints:
irb(main):003:0> phone.phone_number_type = 1; phone.phone_number_type
=> "office"
irb(main):004:0> phone.phone_number_type = "mobile"; phone.phone_number_type
=> "mobile"
หรือแม้แต่ใช้วิธีปัง:
irb(main):005:0> phone.office!
=> true
irb(main):006:0> phone.phone_number_type
=> "office"
คุณจะได้รับวิธีการถามว่าแอตทริบิวต์ของคุณมีค่าเฉพาะหรือไม่:
irb(main):007:0> phone.office?
=> true
และคุณสามารถค้นหา ทั้งหมด วัตถุที่มีค่าที่คุณกำลังมองหา:
irb(main):008:0> Phone.office
Phone Load (0.3ms) SELECT "phones".* FROM "phones" WHERE "phones"."phone_number_type" = ? [["phone_number_type", 1]]
หากคุณต้องการดูค่าต่างๆ ที่คุณสามารถใช้ได้พร้อมกับตัวเลขที่เกี่ยวข้อง ให้ใช้ phone_number_types
วิธีการเรียน:
irb(main):009:0> Phone.phone_number_types
=> {"home"=>0, "office"=>1, "mobile"=>2, "fax"=>3}
ซึ่งทำให้ง่ายต่อการใส่ลงในรูปแบบ HTML:
<div class="field">
<%= f.label :phone_number_type %><br>
<%= f.select :phone_number_type, Phone.phone_number_types.keys %>
</div>
บางสิ่งที่น่าจับตามอง
Enums ไม่ได้ไม่มีปัญหาของพวกเขา คุณต้องจำไว้สองสามเรื่องหากไม่ต้องการให้เกิดปัญหาในภายหลัง
เมื่อคุณกำหนด enum ลำดับมีความสำคัญ ดังนั้น หากคุณกลับไปที่โค้ดของคุณและตัดสินใจว่าค่าเหล่านั้นควรเรียงตามตัวอักษรจริงๆ:
class Phone < ActiveRecord::Base
enum phone_number_type: [:fax, :home, :mobile, :office]
end
โทรศัพท์ของคุณจะไม่มีประเภทที่ถูกต้องอีกต่อไป คุณสามารถแก้ไขปัญหานี้ได้โดยบอก enum
ตัวเลขใดไปกับค่าใด:
class Phone < ActiveRecord::Base
enum phone_number_type: {fax: 3, home: 0, mobile: 2, office: 1}
end
แต่จริงๆ แล้ว ทางเลือกที่ดีที่สุดของคุณคือรักษาลำดับให้สอดคล้องกัน
ปัญหาที่ใหญ่กว่าคือต้องทำอะไรนอกโลกของ Rails แม้ว่า Rails จะเห็นค่า enum เหล่านี้เป็นสตริง แต่ก็เป็นเพียงตัวเลขในฐานข้อมูลของคุณ ดังนั้น คนที่ดูข้อมูลดิบของคุณจะ ไม่ คิดว่าตัวเลขเหล่านั้นหมายถึงอะไร นอกจากนี้ยังหมายความว่าทุกแอปที่อ่านฐานข้อมูลนั้นจะต้องทราบการแมป enum นั้น
คุณสามารถดัมพ์การแมป enum ของคุณไปยังฐานข้อมูลหรือไฟล์ yaml หากคุณต้องการให้คนอื่นเห็นจริงๆ แต่นั่นไม่ใช่แบบแห้ง เพราะตอนนี้คุณกำลังกำหนด enum ของคุณในสองที่ และถ้าคุณจะไปไกลขนาดนั้น มันอาจจะดีกว่าที่จะทำสิ่งที่เราหลีกเลี่ยงในตอนแรก:สร้างโมเดลและการเชื่อมโยงที่แยกจากกันโดยสิ้นเชิง เพื่อให้โทรศัพท์belong_to
a PhoneNumberType.
แต่ถ้าคุณทำให้มันเรียบง่าย enums ก็เป็นวิธีที่ดีในการเริ่มต้น
ป.ล. ในกรณีที่คุณพลาด ฝึกราง กำลังจะรวมอยู่ใน Ruby Book Bundle ที่จะวางจำหน่ายในวันจันทร์ที่ 6 กรกฎาคม รับมันและหนังสือ Ruby ดีๆ อีก 5 เล่มพร้อมส่วนลดมากมาย!