2009-06-29 7 views
22

मेरे पास एक मॉडल है जो acts_as_nested_set कांटा का उपयोग करता है, और मैंने मॉडल को सहेजने के लिए मॉडल में एक विधि जोड़ा है और नोड को एक लेनदेन में सेट में ले जाया है। यह विधि यह सुनिश्चित करने के लिए एक सत्यापन विधि कहती है कि चाल मान्य है, जो सत्य या गलत लौटाती है। अगर सत्यापन विफल रहता है, तो मैं लेनदेन को रोलबैक करने के लिए ActiveRecord::Rollback बढ़ाने के लिए अपनी सहेजने की विधि चाहता हूं, लेकिन कॉलर को भी झूठी वापसी करता हूं।ActiveRecord :: रोलबैक अपवाद कैसे बढ़ाएं और एक मान को एकसाथ वापस कैसे करें?

मेरे मॉडल इस तरह दिखता है:

class Category < ActiveRecord::Base 
    acts_as_nested_set :dependent => :destroy, :scope => :journal 

    def save_with_place_in_set(parent_id) 
    Category.transaction do 
     return false if !save_without_place_in_set 

     if !validate_move parent_id 
     raise ActiveRecord::Rollback and return false 
     else 
     place_in_nested_set parent_id 
     return true 
     end 
    end 
    end 

    alias_method_chain :save, :place_in_set 

    def validate_move(parent_id) 
    # return true or false if the move is valid 
    # ... 
    end 

    def place_in_nested_set(parent_id) 
    # place the node in the correct place in the set 
    # ... 
    end 
end 

हालांकि, जब मैं एक स्थिति है कि विफल हो जाएगा में बचाने फोन, लेन-देन वापस लुढ़का है, लेकिन समारोह nil रिटर्न:

>> c = Category.new(:name => "test") 
=> #<Category id: nil, name: "test" parent_id: nil, lft: nil, rgt: nil> 
>> c.save_with_place_in_set 47 
=> nil 
>> c.errors.full_messages 
=> ["The specified parent is invalid"] 

उत्तर

26

आप मूल्य तुम एक चर में समारोह से लौट आए चाहते स्टोर और वापसी है कि लेनदेन ब्लॉक के बाहर हो सकता है। जैसे

def save_with_place_in_set(parent_id) 
    return_value = false 
    Category.transaction do 
     if !save_without_place_in_set 
     return_value = false 
     elsif !validate_move parent_id 
     return_value = false 
     raise ActiveRecord::Rollback 
     else 
     place_in_nested_set parent_id 
     return_value = true 
     end 
    end 
    return return_value 
    end 

मैं शुरू में ही अन्य तरीके से आपको लगता है कि लेन-देन ब्लॉक से बाहर निकल सकते रूप में गलत पर return_value निर्धारित किया है तो किसी दूसरी विधि का ActiveRecord::Rollback मेरा मानना ​​है कि जन्म देती है।

+0

+1, अनिवार्य रूप से वही निष्कर्ष मैं आया था। –

+0

आपको धन्यवाद! अभी भी रेल 3.2.8 में मान्य है। यह [दस्तावेज़ीकरण] (http://api.rubyonrails.org/classes/ActiveRecord/Rollback.html) से मुझे स्पष्ट नहीं था कि लेनदेन के अंत के बाद लाइन पर ActiveRecord :: रोलबैक कूदता है। ऐसा लगता है कि यह सिर्फ गिर रहा था, हालांकि रोलबैक वास्तव में प्रोग्राम प्रवाह को बाधित नहीं करता था। –

10

क्योंकि ActiveRecord::Rollback अपवाद संभाला जाता है, लेकिन ActiveRecord::Transaction द्वारा फिर से उठाया नहीं गया है, मैं लेनदेन ब्लॉक से अपनी वापसी वापस ले सकता हूं, और लेनदेन के बाद वापस एक मूल्य वापस कर सकता है।

एक छोटे से पुनर्रचना के साथ

:

def save_with_place_in_set(parent_id = nil) 
    Category.transaction do 
    return false if !save_without_place_in_set 
    raise ActiveRecord::Rollback if !validate_move parent_id 

    place_in_nested_set parent_id 
    return true 
    end 

    return false 
end 
-1

मुझे पता है कि यह थोड़ा देर हो सकता है, लेकिन मैं एक ही समस्या में भाग गया और पाया कि लेनदेन ब्लॉक के भीतर आप बस एक अपवाद उठा सकते हैं और उसे बचा सकते हैं ... रेल पूरी तरह से लेनदेन को रोलबैक करता है। तो ActiveRecord :: रोलबैक की कोई आवश्यकता नहीं है।

उदाहरण के लिए:

def create 
    begin 
    Model.transaction do 
     # using create! will cause Exception on validation errors 
     record = Model.create!({name: nil}) 
     check_something_afterwards(record) 
     return true 
    end 
    rescue Exception => e 
    puts e.message 
    return false 
    end 
end 

def check_something_afterwards(record) 
    # just for demonstration purpose 
    raise Exception, "name is missing" if record.name.nil? 
end 

मैं रेल 3.2.15 और रूबी 1.9.3 के साथ काम कर रहा हूँ।

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