एक प्रश्न की कल्पना करें जो या तो "लंबित", "स्वीकृत", या "चिह्नित" हो सकता है। या एक फोन नंबर जो "घर", "कार्यालय", "मोबाइल", या "फैक्स" हो (अगर यह 1982 है)।
कुछ मॉडल इस तरह के डेटा की मांग करते हैं। एक विशेषता जो केवल कुछ अलग-अलग मानों में से एक हो सकती है। और मानों का वह सेट लगभग कभी नहीं बदलता।
यह एक ऐसी स्थिति है जहां, अगर यह सादा रूबी होता, तो आप बस एक प्रतीक का उपयोग करते।
आप एक PhoneNumberType या QuestionStatus मॉडल और इन मानों को रखने के लिए एक belongs_to रिश्ता बना सकते हैं, लेकिन यह इसके लायक नहीं लगता। आप उन्हें एक yaml फ़ाइल में भर सकते हैं, लेकिन अब आपको यह पता लगाने के लिए पूरी तरह से अलग जगह देखनी होगी कि आपका ऑब्जेक्ट क्या कर सकता है।
4.1 में, Rails ने ActiveRecord enums के साथ इस समस्या को हल करने का प्रयास किया।
मॉडल में कुछ मान
ActiveRecord enums बहुत आसान हैं। आप अपने मॉडल को एक integer कॉलम देते हैं:
bin/rails g model phone number:string phone_number_type:integerpre>उन मानों को सूचीबद्ध करें जो वह विशेषता ले सकती है:
app/models/phone.rb class Phone < ActiveRecord::Base enum phone_number_type: [:home, :office, :mobile, :fax] endpre>और अब आप नंबरों के बजाय स्ट्रिंग्स से निपट सकते हैं।
इसके बजाय:
irb(main):001:0> Phone.first.phone_number_type => 3pre>आप यह देखेंगे:
irb(main):002:0> Phone.first.phone_number_type => "fax"pre>आप उस विशेषता को या तो स्ट्रिंग्स या इंट्स का उपयोग करके बदल सकते हैं:
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"pre>या यहां तक कि एक बैंग मेथड का उपयोग करके:
irb(main):005:0> phone.office! => true irb(main):006:0> phone.phone_number_type => "office"pre>आपको यह पूछने के लिए मेथड मिलते हैं कि क्या आपकी विशेषता का कोई विशिष्ट मान है:
irb(main):007:0> phone.office? => truepre>और आप सभी ऑब्जेक्ट्स को उस मान के साथ ढूंढ सकते हैं जिसे आप ढूंढ रहे हैं:
irb(main):008:0> Phone.office Phone Load (0.3ms) SELECT "phones".* FROM "phones" WHERE "phones"."phone_number_type" = ? [["phone_number_type", 1]]pre>यदि आप उन सभी अलग-अलग मानों को देखना चाहते हैं जिनका आप उपयोग कर सकते हैं, साथ ही उन नंबरों के साथ जिनसे वे जुड़े हुए हैं, तो
phone_number_typesक्लास मेथड का उपयोग करें:irb(main):009:0> Phone.phone_number_types => {"home"=>0, "office"=>1, "mobile"=>2, "fax"=>3}pre>जो उन्हें 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>pre>
देखने लायक कुछ चीजें
Enums अपनी समस्याओं के बिना नहीं हैं, हालांकि। आपको कुछ चीजों को ध्यान में रखना होगा अगर आप बाद में मुसीबत में नहीं पड़ना चाहते।
जब आप एक enum परिभाषित करते हैं, तो क्रम मायने रखता है। इसलिए यदि आप अपने कोड पर वापस जाते हैं और तय करते हैं कि उन मानों को वास्तव में वर्णमाला क्रम में होना चाहिए:
app/models/phone.rb class Phone < ActiveRecord::Base enum phone_number_type: [:fax, :home, :mobile, :office] endpre>आपके फोन के पास अब सही प्रकार नहीं होंगे। आप
enumको बता सकते हैं कि कौन सा नंबर किस मान के साथ जाता है, इससे बच सकते हैं:app/models/phone.rb class Phone < ActiveRecord::Base enum phone_number_type: {fax: 3, home: 0, mobile: 2, office: 1} endpre>लेकिन वास्तव में, आपका सबसे अच्छा विकल्प क्रम को सुसंगत रखना है।
एक बड़ी समस्या यह है कि Rails की दुनिया के बाहर क्या करना है। भले ही Rails इन enum मानों को स्ट्रिंग्स के रूप में देखता है, वे आपके डेटाबेस के अंदर सिर्फ नंबर हैं। तो कोई आपके कच्चे डेटा को देख रहा होगा उसे कोई अंदाजा नहीं होगा कि उन नंबरों का क्या मतलब है। इसका यह भी अर्थ है कि उस डेटाबेस को पढ़ने वाला हर ऐप को उस enum मैपिंग को जानना होगा।
अगर आपको वास्तव में अन्य लोगों को उन्हें देखने की आवश्यकता है तो आप अपने enum मैपिंग को डेटाबेस या yaml फ़ाइल में डंप कर सकते हैं। लेकिन यह DRY नहीं है, क्योंकि अब आप अपने enum को दो स्थानों में परिभाषित कर रहे हैं। और अगर आप उस हद तक जा रहे हैं, तो शायद शुरुआत में हम जो टाल रहे थे वह करना बेहतर होगा: एक पूरी तरह से अलग मॉडल और एसोसिएशन बनाएं, ताकि एक Phone
belong_toकरे एक PhoneNumberType को।लेकिन अगर आप इसे सरल रख रहे हैं, तो enums शुरू करने का एक शानदार तरीका है।
पी.एस. यदि आप चूक गए, तो Practicing Rails सोमवार, 6 जुलाई को लॉन्च होने वाले Ruby Book Bundle में शामिल होने जा रहा है। इसे और 5 अन्य बेहतरीन Ruby किताबें भारी छूट पर प्राप्त करें!
