2010-11-21 9 views
10

मेरे पास एक ऐसा एप्लिकेशन है जहां मैं अपने कई मॉडल के लिए नष्ट करने के व्यवहार को ओवरराइड करना चाहता हूं। उपयोग का मामला यह है कि उपयोगकर्ताओं को एक विशेष रिकॉर्ड को हटाने की वैध आवश्यकता हो सकती है, लेकिन वास्तव में डेटाबेस से पंक्ति को हटाने से रेफरेंसियल अखंडता नष्ट हो जाएगी जो अन्य संबंधित मॉडलों को प्रभावित करती है। उदाहरण के लिए, सिस्टम का एक उपयोगकर्ता उस ग्राहक को हटाना चाहता है जिसके साथ वे अब व्यवसाय नहीं करते हैं, लेकिन उस ग्राहक के साथ लेनदेन को बनाए रखने की आवश्यकता है।Rails ActiveRecord व्यवहार को नष्ट करने का सबसे अच्छा तरीका क्या है?

ऐसा लगता है मैं कम से कम दो विकल्प हैं: जरूरी मॉडल में

  1. डुप्लीकेट डेटा को प्रभावी ढंग से अपने डेटा मॉडल denormalizing ताकि हटाए गए रिकॉर्ड से संबंधित डेटा को प्रभावित नहीं करेगा।
  2. ActiveRecord के "नष्ट" व्यवहार को ओवरराइड करने के लिए कुछ ऐसा करने के लिए एक ध्वज सेट करें जो उपयोगकर्ता को "हटाए गए" रिकॉर्ड को इंगित करता है और रिकॉर्ड को छुपाने के लिए इस ध्वज का उपयोग करता है।

क्या मुझे बेहतर तरीका याद आ रहा है?

विकल्प 1 मुझे एक भयानक विचार की तरह लगता है, हालांकि मुझे इसके विपरीत तर्क सुनना अच्छा लगेगा।

विकल्प 2 कुछ हद तक रेल-आश लगता है लेकिन मैं इसे संभालने का सबसे अच्छा तरीका सोच रहा हूं। क्या मुझे अपना खुद का अभिभावक वर्ग बनाना चाहिए जो ActiveRecord :: Base से प्राप्त होता है, वहां नष्ट विधियों को ओवरराइड करता है, फिर उन वर्गों में उस वर्ग से प्राप्त होता है जहां मैं यह व्यवहार चाहता हूं? क्या मुझे खोजक व्यवहार को ओवरराइड करना चाहिए, इसलिए हटाए गए रिकॉर्ड को डिफ़ॉल्ट रूप से वापस नहीं किया जाना चाहिए?

यदि मैंने ऐसा किया, तो मैं गतिशील खोजकर्ताओं को कैसे संभालेगा? नामित क्षेत्रों के बारे में क्या?

उत्तर

8

आप वास्तव में उन रिकॉर्ड फिर से देखने में रुचि नहीं कर रहे हैं, लेकिन केवल परवाह है कि बच्चों को अभी भी मौजूद हैं जब माता-पिता को नष्ट कर दिया जाता है, तो काम आसान है: NULL को माता-पिता के लिए संदर्भ सेट करने के लिए कॉल करने के लिए has_many:dependent => :nullify जोड़ने स्वचालित रूप से विनाश पर, और उस संदर्भ से निपटने के लिए दृश्य को सिखाएं। हालांकि, यह केवल तभी काम करता है जब आप कभी भी पंक्ति को कभी नहीं देख रहे हैं, यानी उन लेनदेन को देखते हुए कंपनी के नाम के तहत "[कोई लंबा EXSTSTS]" दिखाता है।

यदि आप कि डेटा को फिर से देखना चाहते हो, यह लग रहा है क्या आप चाहते हैं वास्तव में , रिकॉर्ड को नष्ट जिसका अर्थ है कि आप फिर से उन्हें करने की जरूरत कभी नहीं होगा के साथ कोई संबंध नहीं है की तरह। छिपाने का रास्ता लगता है।

नष्ट करने को ओवरराइड करने के बजाय, क्योंकि आप वास्तव में रिकॉर्ड को नष्ट नहीं कर रहे हैं, इसलिए आपके व्यवहार को hide विधि में डालने के लिए यह काफी आसान लगता है, जैसा कि आपने सुझाव दिया था।

वहां से, जब भी आप इन रिकॉर्ड्स को सूचीबद्ध करना चाहते हैं और केवल दृश्य रिकॉर्ड शामिल करना चाहते हैं, तो एक सरल समाधान visible स्कोप शामिल करना है जिसमें छिपे हुए रिकॉर्ड शामिल नहीं हैं, और जब आप उस विशिष्ट, छिपे हुए को ढूंढना चाहते हैं तो इसे शामिल न करें फिर से रिकॉर्ड करें। एक और तरीका छिपे हुए रिकॉर्ड को छिपाने के लिए default_scope का उपयोग करना है और एक छिपे हुए रिकॉर्ड को खींचने के लिए Model.with_exclusive_scope { find(id) } का उपयोग करना है, लेकिन मैं इसके खिलाफ अनुशंसा करता हूं, क्योंकि यह आने वाले डेवलपर के लिए गंभीर गॉचाचा हो सकता है, और मूल रूप से Model.all क्या बदलता है प्रतिबिंबित करता है कि विधि कॉल क्या सुझाता है।

मैं नियंत्रकों को रेलवे के तरीके की तरह दिखने की इच्छा को समझता हूं, लेकिन जब आप वास्तव में चीजें रेल तरीके से नहीं कर रहे हैं, तो इसके बारे में स्पष्ट होना सर्वोत्तम है, खासकर जब यह वास्तव में है ऐसा करने के लिए बहुत दर्द नहीं है।

+0

धन्यवाद मिलानू। आप सही हैं, मैं _do_ को फिर से डेटा का उपयोग करने की आवश्यकता है, इसलिए मैं जो खोज रहा हूं वह शून्य नहीं है। जबकि उनके उत्तर में वर्णित रयान की प्लगइन की सादगी आकर्षक है, व्यवहार के बारे में स्पष्ट होने के आपके तर्क ने मुझे राजी किया। मैं प्रतिक्रिया की सराहना करता हूं। –

6

मैंने a plugin for this exact purpose लिखा, जिसे पैरानोआ कहा जाता है। मैंने acts_as_paranoid से विचार "उधार" लिया और मूल रूप से बहुत कम कोड का उपयोग करके आप को फिर से लिखा।

जब आप रिकॉर्ड पर destroy पर कॉल करते हैं, तो यह वास्तव में इसे हटा नहीं देता है। इसके बजाए, यह आपके डेटाबेस में वर्तमान समय में deleted_at कॉलम सेट करेगा।

गिटहब पेज पर README स्थापना & उपयोग के लिए सहायक होना चाहिए। यदि ऐसा नहीं है, तो मुझे बताएं और मैं देखूंगा कि मैं आपके लिए इसे ठीक कर सकता हूं या नहीं।

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