Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

การสร้างแอตทริบิวต์ที่อ่านง่ายด้วย ActiveRecord Enums

ลองนึกภาพคำถามที่อาจเป็น "รอดำเนินการ" "อนุมัติ" หรือ "ติดธง" หรือหมายเลขโทรศัพท์ที่เป็น "บ้าน" "ที่ทำงาน" "มือถือ" หรือ "แฟกซ์" (หากเป็นปี 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

ระบุค่าที่แอตทริบิวต์สามารถรับได้:

app/models/phone.rb
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:

app/views/phones/_form.html.erb
<div class="field">
  <%= f.label :phone_number_type %><br>
  <%= f.select :phone_number_type, Phone.phone_number_types.keys %>
</div>

การสร้างแอตทริบิวต์ที่อ่านง่ายด้วย ActiveRecord Enums

บางสิ่งที่น่าจับตามอง

Enums ไม่ได้ไม่มีปัญหาของพวกเขา คุณต้องจำไว้สองสามเรื่องหากไม่ต้องการให้เกิดปัญหาในภายหลัง

เมื่อคุณกำหนด enum ลำดับมีความสำคัญ ดังนั้น หากคุณกลับไปที่โค้ดของคุณและตัดสินใจว่าค่าเหล่านั้นควรเรียงตามตัวอักษรจริงๆ:

app/models/phone.rb
class Phone < ActiveRecord::Base
  enum phone_number_type: [:fax, :home, :mobile, :office]
end

โทรศัพท์ของคุณจะไม่มีประเภทที่ถูกต้องอีกต่อไป คุณสามารถแก้ไขปัญหานี้ได้โดยบอก enum ตัวเลขใดไปกับค่าใด:

app/models/phone.rb
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 เล่มพร้อมส่วนลดมากมาย!