2011-05-25 12 views
5

क्लोनिंग मैं UserFile कि belongs_to एक Folder एक मॉडल है:मान्यता को नजरअंदाज कर दिया जब एक नव निर्मित रिकॉर्ड

class UserFile < ActiveRecord::Base 
    has_attached_file :attachment 
    belongs_to :folder 

    validates_attachment_presence :attachment 
    validates_presence_of :folder_id 

    def copy(target_folder) 
    new_file = self.clone 
    new_file.folder = target_folder 
    new_file.save! 
    end 
end 

निम्न परीक्षण अप्रत्याशित रूप से विफल रहता है: का उपयोग करते समय एक नव निर्मित

test 'cannot copy a file to anything other than a folder' do 
    folder = Factory(:folder) 
    file1 = UserFile.create(:attachment => File.open("#{Rails.root}/test/fixtures/textfile.txt"), :folder => Folder.root) 
    file2 = UserFile.find(file1) 

    # Should pass, but fails 
    assert_raise(ActiveRecord::RecordInvalid) { file1.copy(nil) } 

    # Same record, but this DOES pass 
    assert_raise(ActiveRecord::RecordInvalid) { file2.copy(nil) } 

    assert file1.copy(folder) 
end 

validates_presence_of :folder_id नजरअंदाज कर दिया है ऑब्जेक्ट, लेकिन जब मैं ActiveRecord#find करता हूं तो यह काम करता है। मुझे लगता है कि clone को copy विधि में कॉल करने के साथ कुछ करना है, लेकिन मैं इसे समझ नहीं सकता। क्या किसी को पता है कि क्या हो रहा है या परीक्षा पास कैसे करें ??

+0

'file1' userfile का एक उदाहरण है लेकिन' file2' आप 'का उपयोग कर रहे UserFile.find (file1) के लिए' जोड़कर हल किया जाता है, मैं लगता है 'UserFile.find (file1.id) ' – JCorcuera

+1

इससे कोई फर्क नहीं पड़ता। आप या तो 'UserFile.find (file1.id) 'या' UserFile.find (file1) 'का उपयोग कर सकते हैं। एक ही बात है। – Mischa

+0

क्या यह आपके विचार के कारण अपवाद उठा रहा है? शायद, आपका सत्यापन किसी भी मामले में काम नहीं कर रहा है, लेकिन दूसरी बचत पर एक अलग सत्यापन विफल हो रहा है - एक अद्वितीय कॉलम में डुप्लिकेट मान के कारण, शायद? –

उत्तर

3

मिशा, क्लोनिंग एक जानवर है।

record.errors को याद किया जाता है और @errors इंस्टेंस वैरिएबल भी क्लोन हो जाता है।

file1.errors = new_file.errors 

इस के बाद से file1 पर create बुलाया सत्यापन गैर शून्य हो जाएगा।

अब जब आप फ़ाइल 1 क्लोन करते हैं और new_file.save! कहते हैं तो क्या होता है? valid? के अंदर दीप त्रुटियों को कॉल करता है। New_file पर स्पष्ट है लेकिन यह अभी भी उसी त्रुटि ऑब्जेक्ट को file1 के रूप में इंगित करता है। अब क्रूरतापूर्वक, उपस्थिति सत्यापनकर्ता इस तरह कार्यान्वित किया जाता है:

def validate(record) 
    record.errors.add_on_blank(attributes, options) 
end 

जो (जाहिर है) केवल पहुँच errors.base कर सकते हैं http://apidock.com/rails/ActiveModel/Errors/add_on_blank

तो है, हालांकि, सत्यापन रिकॉर्ड के रूप में new_file पर चला सकता हूँ, उपस्थिति सत्यापन गुजरता के बाद से

new_file.errors.instance_eval { @base } == file1 

और file1.folder_id के लिए खाली नहीं है।

अब, आपका दूसरा परीक्षण पास हो जाता है क्योंकि यदि आप डीबी से फ़ाइल एंट्री पढ़ते हैं, तो file2.errors शून्य है इसलिए जब आप इसे क्लोन करते हैं और क्लोन पर सत्यापन कॉल करते हैं, तो त्रुटि ऑब्जेक्ट को सही आधार (क्लोन) के साथ नया बनाया जाता है। लाइन के कारण folder_id खाली हो जाएगा।

आपकी समस्या केवल

def copy(target_folder) 
    new_file = self.clone 
    new_file.instance_eval { @errors = nil } # forces new error object on clone 
    new_file.folder = target_folder 
    new_file.save! 
end 

आशा है कि यह मदद की

+0

धन्यवाद !! यदि आपका समाधान काम करता है तो मैं कोशिश करूंगा।यदि ऐसा होता है, तो मैं इसके पीछे तर्क को समझने की कोशिश करूंगा ;-) – Mischa

+0

बहुत बढ़िया !! बहुत बहुत धन्यवाद। यह मुझे पागल कर रहा था। मैं यादों पर पढ़ रहा हूं और अपनी व्याख्या पूरी तरह समझने की कोशिश कर रहा हूं। – Mischa

+1

ज्ञापन बस इतना ही है: 'def त्रुटियाँ @errors || = त्रुटियाँ। नया (स्वयं) अंत', दृश्यमान बात यह है कि सत्यापन त्रुटियों के आधार से रिकॉर्ड लेते हैं, जो बेवकूफ और गैर-पारदर्शी है, मुझे लगता है कि सत्यापन उनके पास पारित रिकॉर्ड है। लेकिन रेल कोर देव कह सकते हैं: अपने जोखिम पर क्लोन :) –

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