2011-12-14 6 views
9

क्या रेल नियंत्रक स्थापित करना संभव है कि सभी नियंत्रक क्रियाएं स्वचालित रूप से लेन-देन के साथ लिपटे हों, जो अनचाहे अपवादों के मामले में स्वचालित रूप से वापस हो जाती है?रेल में लेनदेन में सभी नियंत्रक कार्यों को लपेटें

मैं रेलवे 3 एप्लिकेशन पर काम कर रहा हूं, वर्तमान में एक काफी मुश्किल कार्रवाई के लिए जो कई डेटाबेस परिवर्तन करता है। और मुझे यह गलत हो रहा है, कई बार! थोड़ी देर के बाद मुझे एहसास हुआ कि मेरा कोड काम नहीं कर रहा था क्योंकि मैं डेटाबेस में असंगत डेटा के साथ समाप्त हो गया था।

मैं आसानी से लेनदेन के साथ इसे पर्याप्त रूप से लपेट सकता हूं (यह एक स्पष्ट उदाहरण है जहां किसी की आवश्यकता है!)। हालांकि, मुझे यह सोचने लगा कि कम से कम विकास में, यह विचार प्रत्येक नियंत्रक कार्रवाई में लागू करने के लिए उपयोगी होगा।

मान लीजिए कि यह संभव है, क्या इसका कोई नकारात्मक पक्ष है?

उत्तर

5

क्या यह किया जा सकता है? शायद। क्या यह किया जाना चाहिए? शायद नहीं, अन्यथा यह रेल का हिस्सा होगा, या इसके लिए पहले से ही एक महान मणि होगा।

यदि आपके पास विशेष जटिल नियंत्रक क्रियाएं हैं जो बहुत सी डीबी गतिविधि कर रही हैं, और आप उन्हें लेनदेन में रखना चाहते हैं, तो मेरी सलाह है कि इस व्यापार तर्क और दृढ़ता को मॉडल विधि में प्राप्त करें, और अपना लेनदेन वहां रखें। इससे आपको उन मामलों के लिए अधिक नियंत्रण मिल जाता है जहां आप हमेशा ऐसा नहीं करना चाहते हैं।

आप सच में, सच वैसे भी यह करने के लिए चाहते हैं, तो मुझे यकीन है तुम रैक मिडलवेयर के साथ यह कर सकता है, यह (untested) एक https://gist.github.com/1477287 की तरह:

# make this class in lib/transactional_requests.rb, and load it on start 
require 'activerecord' 

class TransactionalRequests 
    def initialize(app) 
    @app = app 
    end 

    def call(env) 
    ActiveRecord::Base.transaction do 
     @app.call(env) 
    end 
    end 
end 

# and in the app config 
config.middleware.use "TransactionalRequest" 
+0

धन्यवाद। मैं इस बारे में सोचने जा रहा हूं कि यह एक अच्छा विचार है या नहीं। मुझे लगता है कि समस्या यह है कि मैं आवेदन के भीतर उपयोग किए जाने वाले किसी लेनदेन को वास्तव में बाहरी लेनदेन में बंडल कर दूंगा। हालांकि, किसी कारण से इसे देखते हुए, उसने मुझे यह विचार दिया कि इसे कैसे किया जाए। मैं अपने समाधान के साथ पोस्ट करूंगा ताकि कोड अधिक आसानी से पठनीय हो! – asc99c

16

जानकारी के लिए, मैं एक around_filter साथ ऐसा किया अपने आवेदन नियंत्रक में:

around_filter :wrap_in_transaction 

def wrap_in_transaction 
    ActiveRecord::Base.transaction do 
    yield 
    end 
end 

यह सिर्फ किसी भी बिना क्रिया का अपवाद पर लेन-देन वापस रोल, और अपवाद फिर से उठाती है।

+0

मुझे यह विचार पसंद है, लेकिन मैं इसका उपयोग कर बाद_commit और after_rollback कॉलबैक तक कैसे पहुंच सकता हूं? – nexar

+1

मैं दृढ़ता से सुझाव देता हूं कि इसे दोबारा पैदा करने से पहले नींद की रैंड जोड़ें - यह बात आपके मशीन को विस्फोट कर सकती है यदि आपके पास कई समवर्ती लेनदेन हैं। – fotanus

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