2012-01-27 8 views
22

मैंने सोचा कि स्थिरांक तालिका का उपयोग करके एक सक्रिय क्षेत्र तालिका में स्थिति फ़ील्ड को पॉप्युलेट करना अच्छा होगा। हालांकि, यह जांचने की बात आती है कि क्या इस स्थिति की कोई विशेष स्थिति है, मुझे परेशानी हो रही है।स्टोर और तुलना कैसे करें: ActiveRecord (Rails पर रूबी) में प्रतीकों

अगर मैं निम्नलिखित करते हैं,

e = Mytable.new 
e.status = :cancelled 
e.save 

तो रिकॉर्ड refind और कोशिश करते हैं और प्रतीक को मेरी स्थिति की तुलना करें, जाँच विफल रहता है। मेरे पास यह दिखाने के लिए कंसोल से कुछ आउटपुट है।

irb(main):060:0> e.status.eql?("cancelled") 
=> true 
irb(main):061:0> e.status.eql?(:cancelled) 
=> false 
irb(main):062:0> e.status == :cancelled 
=> false 
irb(main):063:0> e.status == "cancelled" 
=> true 
irb(main):064:0> e.status == :cancelled.to_s 
=> true 

क्या रिकॉर्ड में स्थिति रखने का कोई बेहतर तरीका है? यदि कोई मौजूदा फ़ील्ड मान बराबर है तो परीक्षण का कोई तरीका है: बिना किसी स्ट्रिंग के प्रतीक: प्रतीक? मैं सोच रहा हूं कि एक ऑपरेटर हो सकता है जिसे मैं नहीं जानता हूं।

+1

ecoologic आपके लिए एक अच्छा समाधान है, लेकिन मैं शायद इस से दूर स्टीयरिंग और शायद उस में स्थिरांक के साथ एक वर्ग बनाने की सिफारिश करेंगे। कि आप 'e.status = Statuses :: CANCELLED' जैसी चीजें कर सकते हैं और क्या नहीं। और आंतरिक रूप से यह एक स्ट्रिंग हो सकता है और इससे कोई फर्क नहीं पड़ता। आप अभी भी स्थिरांक का उपयोग कर रहे हैं, और यह त्रुटि होगी यदि वह निरंतर मौजूद नहीं है, और यह उस तरह से क्लीनर है। – MrDanA

+0

आप अपने कॉलम के गेटर को ओवरराइड क्यों नहीं करते? – apneadiving

+0

मैंने इन दो टिप्पणियों को पढ़ने से पहले मेरे जवाब में संशोधन किया लेकिन मैं यह कहना चाहूंगा कि मुझे @MrDanA समाधान पसंद है, आपको एक उत्तर लिखना चाहिए और मैं इसे वोट दूंगा! – ecoologic

उत्तर

7

ecoologic के अनुरोध पर, यहाँ एक जवाब के रूप में मेरी टिप्पणी है:

ecoologic आप के लिए एक अच्छा समाधान है, लेकिन मैं इस से दूर स्टीयरिंग की सलाह देते हैं और उस में स्थिरांक के साथ एक वर्ग बनाने जाएगा। कि आप e.status = Statuses :: CANCELED जैसी चीजें कर सकते हैं। और आंतरिक रूप से यह एक स्ट्रिंग हो सकता है और इससे कोई फर्क नहीं पड़ता। आप अभी भी स्थिरांक का उपयोग कर रहे हैं, और यह त्रुटि होगी यदि वह निरंतर मौजूद नहीं है, और यह उस तरह से क्लीनर है।

+0

सर्वोत्तम अभ्यास के मामले में, आप इस कक्षा को कहां रखेंगे? Lib में, या हेल्पर्स में अपनी फ़ाइल में? – seanyboy

+0

मैंने मॉडल फ़ाइल में स्टेटस क्लास रखा है। यह अच्छी तरह से काम कर रहा है। मैंने स्थिति को एक रंग में बदलने के लिए कक्षा में एक self.method भी जोड़ा। तो यह सब एक ही स्थान पर रखता है। – seanyboy

+1

मैं आमतौर पर उन्हें अपनी फाइल में lib में डाल देता हूं, हां। फिर आप अपनी एप्लिकेशन कॉन्फ़िगरेशन फ़ाइल को संपादित करके फ़ाइलों को स्वचालित रूप से लोड कर सकते हैं (उन्हें 'आवश्यकता' होने के बजाय)। – MrDanA

7

यदि मुझे याद है कि ActiveRecord में अच्छी तरह से प्रतीकों को yaml प्रारूप में संग्रहीत किया जाता है, तो कुछ प्रकार का रूपांतरण किया जाना चाहिए क्योंकि संबंधपरक डीबी (जिसे मैं कम से कम जानता हूं) में प्रतीक जैसी कोई चीज़ नहीं है। जब आप इसे पढ़ यह तो एक स्ट्रिंग जो अपने प्रतीक और नहीं भी प्रतीक की स्ट्रिंग मेल नहीं खाएगी, वास्तव में यह कुछ इस तरह होना चाहिए:

:x # => "--- :x\n" 

मुझे लगता है कि इस प्लगइन अपनी समस्या को हल कर सकते हैं, लेकिन मैं हेवन ईमानदारी से इसका इस्तेमाल नहीं किया। https://github.com/zargony/activerecord_symbolize

* संपादित करें *

क्योंकि मुझे याद है उस स्थिति में मैं था और मैं अब ठीक किया जा सकता है अगर मैं गलत हूँ, फिर भी मैं यह सही कोशिश कर रहा हूँ और संग्रहीत मैं ऊपर छोड़ मान (रेल 3.1.3) प्रतीक के मूल्य के साथ एक साधारण स्ट्रिंग है, इसलिए निम्नलिखित पर्याप्त होना चाहिए।

class Example < ActiveRecord::Base 

    def aaa 
    super.to_sym 
    end 

    def aaa=(value) 
    super(value.to_sym) 
    aaa 
    end 

end 

निश्चित रूप से यह मान हमेशा एक प्रतीक होने के लिए बाध्य करेगा

** युग के बाद संपादित करें ** मुझे लगता है कि के रूप में यह स्पष्ट है कि यह इस स्थिति में ठीक है कि DB में यह एक स्ट्रिंग है और तर्क सरल है, लेकिन मैं दृढ़ता से अधिक जटिल तर्क जोड़ने के लिए ओवरराइडिंग डीबी विशेषता विधियों को हतोत्साहित करता हूं।

+1

यह भी ध्यान में रखें कि: उपयोगकर्ता इनपुट पर to_sym का उपयोग करना एक बुरा विचार है: http://www.tricksonrails.com/2010/06/avoid-memory-leaks-in-ruby-rails-code-and-protect-against -डेनियल ऑफ सर्विस/ – oseiskar

+0

हाँ, उल्लेख करने लायक है, यह खराब अभ्यास – ecoologic

1

प्रोग्रामिंग रूबी 1.9, प्रतीक कक्षा में == ऑपरेटर के बारे में से (पी 729।):

Returns true only if sym and obj are symbols with the same object_id. 

तुम जो भी डीबी में संग्रहीत किए गए हमेशा की तय object_id की तुलना में अलग object_id होगा प्रतीक (इस मामले में एक स्ट्रिंग शाब्दिक के लिए एक सूचक)।

5

इसके अलावा, आप reader विधि के ऊपर लिख सकते हैं:

def status 
    read_attribute(:status).to_sym 
end 
8

इस तरह की देर हो चुकी है, लेकिन किसी और मदद मिल सकती है।

आप अलग अलग स्थितियों के साथ वर्गों है, तो आप इस तरह स्कोप के साथ स्थिरांक का उपयोग कर एक दृष्टिकोण पर विचार हो सकता:

class Account < ActiveRecord::Base 
    #------------------------------------------------------------------------------- 
    # Configuration 
    #------------------------------------------------------------------------------- 

    # STATUS is used to denote what state the account is in. 
    STATUS = { :active => 1, :suspended => 2, :closed => 3 } 

    # Scopes 
    scope :active, where(:status => Account::STATUS[:active]) 
    scope :suspended, where(:status => Account::STATUS[:suspended]) 
    scope :closed, where(:status => Account::STATUS[:closed]) 
    ... 
end 

तो आप आसानी से रिकॉर्ड की स्थिति पर आधारित है, इसलिए की तरह पा सकते हैं:

# get all active accounts 
active_accounts = Consumer.active.all 
# get 50 suspended accounts 
suspended_accounts = Consumer.suspended.limit(50) 
# get accounts that are closed and [some search criteria] 
closed_accounts = Consumer.closed.where([some search criteria]) 

उम्मीद है कि यह किसी और की मदद करेगा!

संपादित करें: यदि आप रत्नों का उपयोग करने में अधिक हैं, तो simple_enum मणि एक उत्कृष्ट विकल्प की तरह दिखता है।

12

रेल 4.1.0 के साथ, आप शायद सक्रिय रिकॉर्ड एनम का उपयोग करना चाहते हैं।

2,5 सक्रिय रिकॉर्ड enums

घोषित एक:

class Conversation < ActiveRecord::Base 
  enum status: [ :active, :archived ] 
end 
  
conversation.archived! 
conversation.active? # => false 
conversation.status  # => "archived" 
  
Conversation.archived # => Relation for all archived Conversations 
  
Conversation.statuses # => { "active" => 0, "archived" => 1 } 
6

रेल 4.1 के रूप में, सक्रिय रिकॉर्ड अब enums

release notes से समर्थन करता है:

official release notes के शब्दों में enum विशेषता जहां मानमें पूर्णांक के लिए मानचित्रडेटाबेस, लेकिन नाम से पूछताछ की जा सकती है।

class Conversation < ActiveRecord::Base 
    enum status: [ :active, :archived ] 
end 

conversation.archived! 
conversation.active? # => false 
conversation.status # => "archived" 

Conversation.archived # => Relation for all archived Conversations 

Conversation.statuses # => { "active" => 0, "archived" => 1 } 

अतिरिक्त यहाँ प्रलेखन: http://api.rubyonrails.org/v4.1.0/classes/ActiveRecord/Enum.html

संबंधित मुद्दे