एक प्रश्न की कल्पना करें जो या तो "लंबित", "स्वीकृत" या "ध्वजांकित" हो सकता है। या कोई फ़ोन नंबर जो "घर", "कार्यालय", "मोबाइल" या "फ़ैक्स" हो (यदि यह 1982 का है)।
कुछ मॉडल इस तरह के डेटा की मांग करते हैं। एक विशेषता जिसमें कुछ भिन्न मानों में से केवल एक ही हो सकता है। और मूल्यों का वह सेट लगभग कभी नहीं बदलता है।
यह एक ऐसी स्थिति है, जहां, अगर यह सादा रूबी होता, तो आप केवल एक प्रतीक का उपयोग करते।
आप एक PhoneNumberType या QuestionStatus मॉडल बना सकते हैं और एक belongs_to
इन मूल्यों को धारण करने के लिए संबंध, लेकिन यह इसके लायक नहीं लगता है। आप उन्हें yaml फ़ाइल में भर सकते हैं, लेकिन अब आपको यह पता लगाने के लिए पूरी तरह से अलग जगह पर देखना होगा कि आपकी वस्तु क्या कर सकती है।
4.1 में, रेल ने ActiveRecord एनम के साथ इस समस्या को हल करने के लिए एक कदम उठाया।
मॉडल में कुछ मान
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"
आप बदल कर सकते हैं वह विशेषता या तो स्ट्रिंग्स या इनट्स का उपयोग करती है:
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 हालांकि उनकी समस्याओं के बिना नहीं हैं। अगर आप आगे चलकर परेशानी में नहीं पड़ना चाहते हैं तो आपको कुछ बातों का ध्यान रखना होगा।
जब आप एक एनम को परिभाषित करते हैं, तो आदेश मायने रखता है। इसलिए यदि आप अपने कोड पर वापस जाते हैं और तय करते हैं कि वे मान वास्तव में वर्णानुक्रम में होने चाहिए:
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
लेकिन वास्तव में, आपका सबसे अच्छा विकल्प है कि आप ऑर्डर को एक समान रखें।
एक बड़ी समस्या यह है कि रेल जगत के बाहर क्या किया जाए। भले ही रेल इन एनम मानों को स्ट्रिंग्स के रूप में देखता है, वे आपके डेटाबेस के अंदर केवल संख्याएं हैं। तो आपके अपरिष्कृत डेटा को देखने वाले के पास नहीं होगा जानिए उन नंबरों का क्या मतलब है। इसका मतलब यह भी है कि उस डेटाबेस को पढ़ने वाले हर ऐप को उस एनम मैपिंग को जानना होगा।
आप अपने एनम मैपिंग को डेटाबेस या एक yaml फ़ाइल में डंप कर सकते हैं यदि आपको वास्तव में उन्हें देखने के लिए अन्य लोगों की आवश्यकता है। लेकिन यह DRY नहीं है, क्योंकि अब आप अपने एनम को दो स्थानों पर परिभाषित कर रहे हैं। और अगर आप इतनी दूर जा रहे हैं, तो बेहतर होगा कि हम वही करें जो हम शुरुआत में टाल रहे थे:एक पूरी तरह से अलग मॉडल और जुड़ाव बनाएं, ताकि एक फोन belong_to
हो सके। एक PhoneNumberType.
लेकिन अगर आप इसे सरल रख रहे हैं, तो एनम शुरू करने का एक शानदार तरीका है।
पी.एस. यदि आप चूक गए हैं, तो रेल का अभ्यास करना रूबी बुक बंडल में शामिल होने जा रहा है, जो सोमवार 6 जुलाई को लॉन्च हो रहा है। इसे और 5 अन्य बेहतरीन रूबी किताबें भारी छूट पर प्राप्त करें!